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 #include <txtfrm.hxx>
28 #include <flyfrm.hxx>
29 #include <ndtxt.hxx>
30 #include <pam.hxx>
31 #include <unotextrange.hxx>
32 #include <unocrsrhelper.hxx>
33 #include <crstate.hxx>
34 #include <accmap.hxx>
35 #include <fesh.hxx>
36 #include <viewopt.hxx>
37 #include <vos/mutex.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/window.hxx>
40 #include <rtl/ustrbuf.hxx>
41 #include <com/sun/star/accessibility/AccessibleRole.hpp>
42 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
43 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
44 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
45 #include <unotools/accessiblestatesethelper.hxx>
46 #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
47 #include <com/sun/star/i18n/WordType.hpp>
48 #include <com/sun/star/i18n/XBreakIterator.hpp>
49 #include <com/sun/star/beans/UnknownPropertyException.hpp>
50 #include <breakit.hxx>
51 #include <accpara.hxx>
52 #include <access.hrc>
53 #include <accportions.hxx>
54 #include <sfx2/viewsh.hxx> // for ExecuteAtViewShell(...)
55 #include <sfx2/viewfrm.hxx> // for ExecuteAtViewShell(...)
56 #include <sfx2/dispatch.hxx> // for ExecuteAtViewShell(...)
57 #include <unotools/charclass.hxx> // for GetWordBoundary
58 // for get/setCharacterAttribute(...)
59
60 #include <reffld.hxx>
61 #include <docufld.hxx>
62 #include <expfld.hxx>
63 #include <flddat.hxx>
64 #include <fldui.hrc>
65 #include "../../ui/inc/fldmgr.hxx"
66 #include "fldbas.hxx" // SwField
67 #include <svl/svstdarr.hxx>
68 #include <unocrsr.hxx>
69 //#include <unoobj.hxx>
70 #include <unoport.hxx>
71 #include <doc.hxx>
72 #include <crsskip.hxx>
73 #include <txtatr.hxx>
74 #include <acchyperlink.hxx>
75 #include <acchypertextdata.hxx>
76 #include <unotools/accessiblerelationsethelper.hxx>
77 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
78 #include <section.hxx>
79 #include <doctxm.hxx>
80 #include <comphelper/accessibletexthelper.hxx>
81 #include <algorithm>
82 #include <docufld.hxx>
83 #include <txtfld.hxx>
84 #include <fmtfld.hxx>
85 #include <modcfg.hxx>
86 //#include "accnote.hxx"
87 #include <com/sun/star/beans/XPropertySet.hpp>
88 #include "swmodule.hxx"
89 #include "redline.hxx"
90 #include <com/sun/star/awt/FontWeight.hpp>
91 #include <com/sun/star/awt/FontStrikeout.hpp>
92 #include <com/sun/star/awt/FontSlant.hpp>
93 #include <wrong.hxx>
94 #include <editeng/brshitem.hxx>
95 #include <swatrset.hxx>
96 #include <frmatr.hxx>
97 #include <unosett.hxx>
98 #include <paratr.hxx>
99 #include <com/sun/star/container/XIndexReplace.hpp>
100 // --> OD 2006-07-12 #i63870#
101 #include <unomap.hxx>
102 #include <unoprnms.hxx>
103 #include <com/sun/star/text/WritingMode2.hpp>
104 #include <editeng/brshitem.hxx>
105 #include <viewimp.hxx>
106 #include <boost/scoped_ptr.hpp>
107 #include <textmarkuphelper.hxx>
108 // --> OD 2010-02-22 #i10825#
109 #include <parachangetrackinginfo.hxx>
110 #include <com/sun/star/text/TextMarkupType.hpp>
111 // <--
112 // --> OD 2010-03-08 #i92233#
113 #include <comphelper/stlunosequence.hxx>
114 // <--
115
116 #include <algorithm>
117
118 using namespace ::com::sun::star;
119 using namespace ::com::sun::star::accessibility;
120 using namespace ::com::sun::star::container;
121 using ::rtl::OUString;
122
123 using beans::PropertyValue;
124 using beans::XMultiPropertySet;
125 using beans::UnknownPropertyException;
126 using beans::PropertyState_DIRECT_VALUE;
127
128 using std::max;
129 using std::min;
130 using std::sort;
131
132 namespace com { namespace sun { namespace star {
133 namespace text {
134 class XText;
135 }
136 } } }
137
138
139 const sal_Char sServiceName[] = "com.sun.star.text.AccessibleParagraphView";
140 const sal_Char sImplementationName[] = "com.sun.star.comp.Writer.SwAccessibleParagraphView";
141 const xub_StrLen MAX_DESC_TEXT_LEN = 40;
GetTxtNode() const142 const SwTxtNode* SwAccessibleParagraph::GetTxtNode() const
143 {
144 const SwFrm* pFrm = GetFrm();
145 DBG_ASSERT( pFrm->IsTxtFrm(), "The text frame has mutated!" );
146
147 const SwTxtNode* pNode = static_cast<const SwTxtFrm*>(pFrm)->GetTxtNode();
148 DBG_ASSERT( pNode != NULL, "A text frame without a text node." );
149
150 return pNode;
151 }
152
GetString()153 ::rtl::OUString SwAccessibleParagraph::GetString()
154 {
155 return GetPortionData().GetAccessibleString();
156 }
157
GetDescription()158 ::rtl::OUString SwAccessibleParagraph::GetDescription()
159 {
160 // --> OD 2004-09-29 #117933# - provide empty description for paragraphs
161 return ::rtl::OUString();
162 // <--
163 }
164
GetCaretPos()165 sal_Int32 SwAccessibleParagraph::GetCaretPos()
166 {
167 sal_Int32 nRet = -1;
168
169 // get the selection's point, and test whether it's in our node
170 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
171 SwPaM* pCaret = GetCursor( false ); // caret is first PaM in PaM-ring
172 // <--
173 if( pCaret != NULL )
174 {
175 const SwTxtNode* pNode = GetTxtNode();
176
177 // check whether the point points into 'our' node
178 SwPosition* pPoint = pCaret->GetPoint();
179 if( pNode->GetIndex() == pPoint->nNode.GetIndex() )
180 {
181 // same node? Then check whether it's also within 'our' part
182 // of the paragraph
183 sal_uInt16 nIndex = pPoint->nContent.GetIndex();
184 if(!GetPortionData().IsValidCorePosition( nIndex ) ||
185 ( GetPortionData().IsZeroCorePositionData() && nIndex== 0) )
186 {
187 SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() );
188 bool bFormat = (pTxtFrm && pTxtFrm->HasPara());
189 if(bFormat)
190 {
191 ClearPortionData();
192 UpdatePortionData();
193 }
194 }
195 if( GetPortionData().IsValidCorePosition( nIndex ) )
196 {
197 // Yes, it's us!
198 // --> OD 2006-10-19 #70538#
199 // consider that cursor/caret is in front of the list label
200 if ( pCaret->IsInFrontOfLabel() )
201 {
202 nRet = 0;
203 }
204 else
205 {
206 nRet = GetPortionData().GetAccessiblePosition( nIndex );
207 }
208 // <--
209
210 DBG_ASSERT( nRet >= 0, "invalid cursor?" );
211 DBG_ASSERT( nRet <= GetPortionData().GetAccessibleString().
212 getLength(), "invalid cursor?" );
213 }
214 // else: in this paragraph, but in different frame
215 }
216 // else: not in this paragraph
217 }
218 // else: no cursor -> no caret
219
220 return nRet;
221 }
222
GetSelection(sal_Int32 & nStart,sal_Int32 & nEnd)223 sal_Bool SwAccessibleParagraph::GetSelection(
224 sal_Int32& nStart, sal_Int32& nEnd)
225 {
226 sal_Bool bRet = sal_False;
227 nStart = -1;
228 nEnd = -1;
229
230 // get the selection, and test whether it affects our text node
231 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
232 SwPaM* pCrsr = GetCursor( true );
233 // <--
234 if( pCrsr != NULL )
235 {
236 // get SwPosition for my node
237 const SwTxtNode* pNode = GetTxtNode();
238 sal_uLong nHere = pNode->GetIndex();
239
240 // iterate over ring
241 SwPaM* pRingStart = pCrsr;
242 do
243 {
244 // ignore, if no mark
245 if( pCrsr->HasMark() )
246 {
247 // check whether nHere is 'inside' pCrsr
248 SwPosition* pStart = pCrsr->Start();
249 sal_uLong nStartIndex = pStart->nNode.GetIndex();
250 SwPosition* pEnd = pCrsr->End();
251 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
252 if( ( nHere >= nStartIndex ) &&
253 ( nHere <= nEndIndex ) )
254 {
255 // translate start and end positions
256
257 // start position
258 sal_Int32 nLocalStart = -1;
259 if( nHere > nStartIndex )
260 {
261 // selection starts in previous node:
262 // then our local selection starts with the paragraph
263 nLocalStart = 0;
264 }
265 else
266 {
267 DBG_ASSERT( nHere == nStartIndex,
268 "miscalculated index" );
269
270 // selection starts in this node:
271 // then check whether it's before or inside our part of
272 // the paragraph, and if so, get the proper position
273 sal_uInt16 nCoreStart = pStart->nContent.GetIndex();
274 if( nCoreStart <
275 GetPortionData().GetFirstValidCorePosition() )
276 {
277 nLocalStart = 0;
278 }
279 else if( nCoreStart <=
280 GetPortionData().GetLastValidCorePosition() )
281 {
282 DBG_ASSERT(
283 GetPortionData().IsValidCorePosition(
284 nCoreStart ),
285 "problem determining valid core position" );
286
287 nLocalStart =
288 GetPortionData().GetAccessiblePosition(
289 nCoreStart );
290 }
291 }
292
293 // end position
294 sal_Int32 nLocalEnd = -1;
295 if( nHere < nEndIndex )
296 {
297 // selection ends in following node:
298 // then our local selection extends to the end
299 nLocalEnd = GetPortionData().GetAccessibleString().
300 getLength();
301 }
302 else
303 {
304 DBG_ASSERT( nHere == nEndIndex,
305 "miscalculated index" );
306
307 // selection ends in this node: then select everything
308 // before our part of the node
309 sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex();
310 if( nCoreEnd >
311 GetPortionData().GetLastValidCorePosition() )
312 {
313 // selection extends beyond out part of this para
314 nLocalEnd = GetPortionData().GetAccessibleString().
315 getLength();
316 }
317 else if( nCoreEnd >=
318 GetPortionData().GetFirstValidCorePosition() )
319 {
320 // selection is inside our part of this para
321 DBG_ASSERT(
322 GetPortionData().IsValidCorePosition(
323 nCoreEnd ),
324 "problem determining valid core position" );
325
326 nLocalEnd = GetPortionData().GetAccessiblePosition(
327 nCoreEnd );
328 }
329 }
330
331 if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
332 {
333 nStart = nLocalStart;
334 nEnd = nLocalEnd;
335 bRet = sal_True;
336 }
337 }
338 // else: this PaM doesn't point to this paragraph
339 }
340 // else: this PaM is collapsed and doesn't select anything
341
342 // next PaM in ring
343 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
344 }
345 while( !bRet && (pCrsr != pRingStart) );
346 }
347 // else: nocursor -> no selection
348
349 return bRet;
350 }
351
352 // --> OD 2005-12-20 #i27301# - new parameter <_bForSelection>
GetCursor(const bool _bForSelection)353 SwPaM* SwAccessibleParagraph::GetCursor( const bool _bForSelection )
354 {
355 // get the cursor shell; if we don't have any, we don't have a
356 // cursor/selection either
357 SwPaM* pCrsr = NULL;
358 SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
359 // --> OD 2005-12-20 #i27301#
360 // - if cursor is retrieved for selection, the cursors for a table selection
361 // has to be returned.
362 if ( pCrsrShell != NULL &&
363 ( _bForSelection || !pCrsrShell->IsTableMode() ) )
364 // <--
365 {
366 SwFEShell *pFESh = pCrsrShell->ISA( SwFEShell )
367 ? static_cast< SwFEShell * >( pCrsrShell ) : 0;
368 if( !pFESh ||
369 !(pFESh->IsFrmSelected() || pFESh->IsObjSelected() > 0) )
370 {
371 // get the selection, and test whether it affects our text node
372 pCrsr = pCrsrShell->GetCrsr( sal_False /* ??? */ );
373 }
374 }
375
376 return pCrsr;
377 }
378
IsHeading() const379 sal_Bool SwAccessibleParagraph::IsHeading() const
380 {
381 const SwTxtNode *pTxtNd = GetTxtNode();
382 return pTxtNd->IsOutline();
383 }
384
GetStates(::utl::AccessibleStateSetHelper & rStateSet)385 void SwAccessibleParagraph::GetStates(
386 ::utl::AccessibleStateSetHelper& rStateSet )
387 {
388 SwAccessibleContext::GetStates( rStateSet );
389
390 // MULTILINE
391 rStateSet.AddState( AccessibleStateType::MULTI_LINE );
392
393 // MULTISELECTABLE
394 SwCrsrShell *pCrsrSh = GetCrsrShell();
395 if( pCrsrSh )
396 rStateSet.AddState( AccessibleStateType::MULTI_SELECTABLE );
397
398 // FOCUSABLE
399 if( pCrsrSh )
400 rStateSet.AddState( AccessibleStateType::FOCUSABLE );
401
402 // FOCUSED (simulates node index of cursor)
403 // --> OD 2005-12-20 #i27301# - consider adjusted method signature
404 SwPaM* pCaret = GetCursor( false );
405 // <--
406 const SwTxtNode* pTxtNd = GetTxtNode();
407 if( pCaret != 0 && pTxtNd != 0 &&
408 pTxtNd->GetIndex() == pCaret->GetPoint()->nNode.GetIndex() &&
409 nOldCaretPos != -1)
410 {
411 Window *pWin = GetWindow();
412 if( pWin && pWin->HasFocus() )
413 rStateSet.AddState( AccessibleStateType::FOCUSED );
414 ::vos::ORef < SwAccessibleContext > xThis( this );
415 GetMap()->SetCursorContext( xThis );
416 }
417 }
418
_InvalidateContent(sal_Bool bVisibleDataFired)419 void SwAccessibleParagraph::_InvalidateContent( sal_Bool bVisibleDataFired )
420 {
421 ::rtl::OUString sOldText( GetString() );
422
423 ClearPortionData();
424
425 const ::rtl::OUString& rText = GetString();
426
427 if( rText != sOldText )
428 {
429 // The text is changed
430 AccessibleEventObject aEvent;
431 aEvent.EventId = AccessibleEventId::TEXT_CHANGED;
432
433 // determine exact changes between sOldText and rText
434 comphelper::OCommonAccessibleText::implInitTextChangedEvent(
435 sOldText, rText,
436 aEvent.OldValue, aEvent.NewValue );
437
438 FireAccessibleEvent( aEvent );
439 uno::Reference< XAccessible > xparent = getAccessibleParent();
440 uno::Reference< XAccessibleContext > xAccContext(xparent,uno::UNO_QUERY);
441 if (xAccContext.is() && xAccContext->getAccessibleRole() == AccessibleRole::TABLE_CELL)
442 {
443 SwAccessibleContext* pPara = static_cast< SwAccessibleContext* >(xparent.get());
444 if(pPara)
445 {
446 AccessibleEventObject aParaEvent;
447 aParaEvent.EventId = AccessibleEventId::VALUE_CHANGED;
448 pPara->FireAccessibleEvent(aParaEvent);
449 }
450 }
451 }
452 else if( !bVisibleDataFired )
453 {
454 FireVisibleDataEvent();
455 }
456
457 sal_Bool bNewIsHeading = IsHeading();
458 //Get the real heading level, Heading1 ~ Heading10
459 nHeadingLevel = GetRealHeadingLevel();
460 sal_Bool bOldIsHeading;
461 {
462 vos::OGuard aGuard( aMutex );
463 bOldIsHeading = bIsHeading;
464 if( bIsHeading != bNewIsHeading )
465 bIsHeading = bNewIsHeading;
466 }
467
468
469 if( bNewIsHeading != bOldIsHeading || rText != sOldText )
470 {
471 ::rtl::OUString sNewDesc( GetDescription() );
472 ::rtl::OUString sOldDesc;
473 {
474 vos::OGuard aGuard( aMutex );
475 sOldDesc = sDesc;
476 if( sDesc != sNewDesc )
477 sDesc = sNewDesc;
478 }
479
480 if( sNewDesc != sOldDesc )
481 {
482 // The text is changed
483 AccessibleEventObject aEvent;
484 aEvent.EventId = AccessibleEventId::DESCRIPTION_CHANGED;
485 aEvent.OldValue <<= sOldDesc;
486 aEvent.NewValue <<= sNewDesc;
487
488 FireAccessibleEvent( aEvent );
489 }
490 }
491 }
492
_InvalidateCursorPos()493 void SwAccessibleParagraph::_InvalidateCursorPos()
494 {
495 // The text is changed
496 sal_Int32 nNew = GetCaretPos();
497 sal_Int32 nOld;
498 {
499 vos::OGuard aGuard( aMutex );
500 nOld = nOldCaretPos;
501 nOldCaretPos = nNew;
502 }
503 if( -1 != nNew )
504 {
505 // remember that object as the one that has the caret. This is
506 // necessary to notify that object if the cursor leaves it.
507 ::vos::ORef < SwAccessibleContext > xThis( this );
508 GetMap()->SetCursorContext( xThis );
509 }
510
511 Window *pWin = GetWindow();
512 if( nOld != nNew )
513 {
514 // The cursor's node position is sumilated by the focus!
515 if( pWin && pWin->HasFocus() && -1 == nOld )
516 FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_True );
517
518
519 AccessibleEventObject aEvent;
520 aEvent.EventId = AccessibleEventId::CARET_CHANGED;
521 aEvent.OldValue <<= nOld;
522 aEvent.NewValue <<= nNew;
523
524 FireAccessibleEvent( aEvent );
525
526 if( pWin && pWin->HasFocus() && -1 == nNew )
527 FireStateChangedEvent( AccessibleStateType::FOCUSED, sal_False );
528 //To send TEXT_SELECTION_CHANGED event
529 sal_Int32 nStart=0;
530 sal_Int32 nEnd =0;
531 sal_Bool bCurSelection=GetSelection(nStart,nEnd);
532 if(m_bLastHasSelection || bCurSelection )
533 {
534 aEvent.EventId = AccessibleEventId::TEXT_SELECTION_CHANGED;
535 aEvent.OldValue <<= uno::Any();
536 aEvent.NewValue <<= uno::Any();
537 FireAccessibleEvent(aEvent);
538 }
539 m_bLastHasSelection =bCurSelection;
540 }
541 }
542
_InvalidateFocus()543 void SwAccessibleParagraph::_InvalidateFocus()
544 {
545 Window *pWin = GetWindow();
546 if( pWin )
547 {
548 sal_Int32 nPos;
549 {
550 vos::OGuard aGuard( aMutex );
551 nPos = nOldCaretPos;
552 }
553 ASSERT( nPos != -1, "focus object should be selected" );
554
555 FireStateChangedEvent( AccessibleStateType::FOCUSED,
556 pWin->HasFocus() && nPos != -1 );
557 }
558 }
559
SwAccessibleParagraph(SwAccessibleMap & rInitMap,const SwTxtFrm & rTxtFrm)560 SwAccessibleParagraph::SwAccessibleParagraph(
561 SwAccessibleMap& rInitMap,
562 const SwTxtFrm& rTxtFrm )
563 // --> OD 2010-02-24 #i108125#
564 : SwClient( const_cast<SwTxtNode*>(rTxtFrm.GetTxtNode()) )
565 // <--
566 , SwAccessibleContext( &rInitMap, AccessibleRole::PARAGRAPH, &rTxtFrm )
567 , sDesc()
568 , pPortionData( NULL )
569 , pHyperTextData( NULL )
570 , nOldCaretPos( -1 )
571 , bIsHeading( sal_False )
572 //Get the real heading level, Heading1 ~ Heading10
573 , nHeadingLevel (-1)
574 , aSelectionHelper( *this )
575 // --> OD 2010-02-19 #i108125#
576 , mpParaChangeTrackInfo( new SwParaChangeTrackingInfo( rTxtFrm ) )
577 // <--
578 , m_bLastHasSelection(false) //To add TEXT_SELECTION_CHANGED event
579 {
580 vos::OGuard aGuard(Application::GetSolarMutex());
581
582 bIsHeading = IsHeading();
583 //Get the real heading level, Heading1 ~ Heading10
584 nHeadingLevel = GetRealHeadingLevel();
585 // --> OD 2004-09-27 #117970# - set an empty accessibility name for paragraphs
586 SetName( ::rtl::OUString() );
587 // <--
588
589 // If this object has the focus, then it is remembered by the map itself.
590 // not necessary to remember this pos here. Generally, the pos will be updated in invalidateXXX method, which may fire the
591 //Focus event based on the difference of new & old caret pos.
592 //nOldCaretPos = GetCaretPos();
593 }
594
~SwAccessibleParagraph()595 SwAccessibleParagraph::~SwAccessibleParagraph()
596 {
597 if(Application::GetUnoWrapper())
598 vos::OGuard aGuard(Application::GetSolarMutex());
599
600 delete pPortionData;
601 delete pHyperTextData;
602 // --> OD 2010-02-22 #i108125#
603 delete mpParaChangeTrackInfo;
604 // <--
605 }
606
HasCursor()607 sal_Bool SwAccessibleParagraph::HasCursor()
608 {
609 vos::OGuard aGuard( aMutex );
610 return nOldCaretPos != -1;
611 }
612
UpdatePortionData()613 void SwAccessibleParagraph::UpdatePortionData()
614 throw( uno::RuntimeException )
615 {
616 // obtain the text frame
617 DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
618 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
619 const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
620
621 // build new portion data
622 delete pPortionData;
623 pPortionData = new SwAccessiblePortionData(
624 pFrm->GetTxtNode(), GetMap()->GetShell()->GetViewOptions() );
625 pFrm->VisitPortions( *pPortionData );
626
627 DBG_ASSERT( pPortionData != NULL, "UpdatePortionData() failed" );
628 }
629
ClearPortionData()630 void SwAccessibleParagraph::ClearPortionData()
631 {
632 delete pPortionData;
633 pPortionData = NULL;
634
635 delete pHyperTextData;
636 pHyperTextData = 0;
637 }
638
639
ExecuteAtViewShell(sal_uInt16 nSlot)640 void SwAccessibleParagraph::ExecuteAtViewShell( sal_uInt16 nSlot )
641 {
642 DBG_ASSERT( GetMap() != NULL, "no map?" );
643 ViewShell* pViewShell = GetMap()->GetShell();
644
645 DBG_ASSERT( pViewShell != NULL, "View shell exptected!" );
646 SfxViewShell* pSfxShell = pViewShell->GetSfxViewShell();
647
648 DBG_ASSERT( pSfxShell != NULL, "SfxViewShell shell exptected!" );
649 if( !pSfxShell )
650 return;
651
652 SfxViewFrame *pFrame = pSfxShell->GetViewFrame();
653 DBG_ASSERT( pFrame != NULL, "View frame exptected!" );
654 if( !pFrame )
655 return;
656
657 SfxDispatcher *pDispatcher = pFrame->GetDispatcher();
658 DBG_ASSERT( pDispatcher != NULL, "Dispatcher exptected!" );
659 if( !pDispatcher )
660 return;
661
662 pDispatcher->Execute( nSlot );
663 }
664
CreateUnoPortion(sal_Int32 nStartIndex,sal_Int32 nEndIndex)665 SwXTextPortion* SwAccessibleParagraph::CreateUnoPortion(
666 sal_Int32 nStartIndex,
667 sal_Int32 nEndIndex )
668 {
669 DBG_ASSERT( (IsValidChar(nStartIndex, GetString().getLength()) &&
670 (nEndIndex == -1)) ||
671 IsValidRange(nStartIndex, nEndIndex, GetString().getLength()),
672 "please check parameters before calling this method" );
673
674 sal_uInt16 nStart = GetPortionData().GetModelPosition( nStartIndex );
675 sal_uInt16 nEnd = (nEndIndex == -1) ? (nStart + 1) :
676 GetPortionData().GetModelPosition( nEndIndex );
677
678 // create UNO cursor
679 SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() );
680 SwIndex aIndex( pTxtNode, nStart );
681 SwPosition aStartPos( *pTxtNode, aIndex );
682 SwUnoCrsr* pUnoCursor = pTxtNode->GetDoc()->CreateUnoCrsr( aStartPos );
683 pUnoCursor->SetMark();
684 pUnoCursor->GetMark()->nContent = nEnd;
685
686 // create a (dummy) text portion to be returned
687 uno::Reference<text::XText> aEmpty;
688 SwXTextPortion* pPortion =
689 new SwXTextPortion ( pUnoCursor, aEmpty, PORTION_TEXT);
690 delete pUnoCursor;
691
692 return pPortion;
693 }
694
695
696 //
697 // range checking for parameter
698 //
699
IsValidChar(sal_Int32 nPos,sal_Int32 nLength)700 sal_Bool SwAccessibleParagraph::IsValidChar(
701 sal_Int32 nPos, sal_Int32 nLength)
702 {
703 return (nPos >= 0) && (nPos < nLength);
704 }
705
IsValidPosition(sal_Int32 nPos,sal_Int32 nLength)706 sal_Bool SwAccessibleParagraph::IsValidPosition(
707 sal_Int32 nPos, sal_Int32 nLength)
708 {
709 return (nPos >= 0) && (nPos <= nLength);
710 }
711
IsValidRange(sal_Int32 nBegin,sal_Int32 nEnd,sal_Int32 nLength)712 sal_Bool SwAccessibleParagraph::IsValidRange(
713 sal_Int32 nBegin, sal_Int32 nEnd, sal_Int32 nLength)
714 {
715 return IsValidPosition(nBegin, nLength) && IsValidPosition(nEnd, nLength);
716 }
GetTOXSortTabBase()717 SwTOXSortTabBase* SwAccessibleParagraph::GetTOXSortTabBase()
718 {
719 const SwTxtNode* pTxtNd = GetTxtNode();
720 if( pTxtNd )
721 {
722 const SwSectionNode * pSectNd = pTxtNd->FindSectionNode();
723 if( pSectNd )
724 {
725 const SwSection * pSect = &pSectNd->GetSection();
726 SwTOXBaseSection *pTOXBaseSect = (SwTOXBaseSection *)pSect;
727 if( pSect->GetType() == TOX_CONTENT_SECTION )
728 {
729 SwTOXSortTabBase* pSortBase = 0;
730 int nSize = pTOXBaseSect->GetTOXSortTabBases()->Count();
731
732 for(int nIndex = 0; nIndex<nSize; nIndex++ )
733 {
734 pSortBase = (*(pTOXBaseSect->GetTOXSortTabBases()))[nIndex];
735 if( pSortBase->pTOXNd == pTxtNd )
736 break;
737 }
738
739 if (pSortBase)
740 {
741 return pSortBase;
742 }
743 }
744 }
745 }
746 return NULL;
747 }
748
GetTOCLevel()749 short SwAccessibleParagraph::GetTOCLevel()
750 {
751 SwTOXSortTabBase* pToxBase = GetTOXSortTabBase();
752 if( pToxBase )
753 {
754 const SwCntntNode* pNd = pToxBase->aTOXSources[0].pNd;
755 if( pNd )
756 return pToxBase->GetLevel();
757 else
758 return -1;
759 }
760 else
761 return -1;
762 }
763
764 //the function is to check whether the position is in a redline range.
GetRedlineAtIndex(sal_Int32)765 const SwRedline* SwAccessibleParagraph::GetRedlineAtIndex( sal_Int32 )
766 {
767 const SwRedline* pRedline = NULL;
768 SwPaM* pCrSr = GetCursor( true );
769 if ( pCrSr )
770 {
771 SwPosition* pStart = pCrSr->Start();
772 const SwTxtNode* pNode = GetTxtNode();
773 if ( pNode )
774 {
775 const SwDoc* pDoc = pNode->GetDoc();
776 if ( pDoc )
777 {
778 pRedline = pDoc->GetRedline( *pStart, NULL );
779 }
780 }
781 }
782
783 return pRedline;
784 }
785
786 //
787 // text boundaries
788 //
789
790
GetCharBoundary(i18n::Boundary & rBound,const::rtl::OUString &,sal_Int32 nPos)791 sal_Bool SwAccessibleParagraph::GetCharBoundary(
792 i18n::Boundary& rBound,
793 const ::rtl::OUString&,
794 sal_Int32 nPos )
795 {
796 if( GetPortionData().FillBoundaryIFDateField( rBound, nPos) )
797 return sal_True;
798
799 rBound.startPos = nPos;
800 rBound.endPos = nPos+1;
801 return sal_True;
802 }
803
GetWordBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32 nPos)804 sal_Bool SwAccessibleParagraph::GetWordBoundary(
805 i18n::Boundary& rBound,
806 const ::rtl::OUString& rText,
807 sal_Int32 nPos )
808 {
809 sal_Bool bRet = sal_False;
810
811 // now ask the Break-Iterator for the word
812 DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
813 DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
814 if( pBreakIt->GetBreakIter().is() )
815 {
816 // get locale for this position
817 sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
818 lang::Locale aLocale = pBreakIt->GetLocale(
819 GetTxtNode()->GetLang( nModelPos ) );
820
821 // which type of word are we interested in?
822 // (DICTIONARY_WORD includes punctuation, ANY_WORD doesn't.)
823 const sal_uInt16 nWordType = i18n::WordType::ANY_WORD;
824
825 /*
826 // get word boundary, as the Break-Iterator sees fit.
827 sal_Unicode SpaceChar(' ');
828 if (rText.getCodePointAt(nPos) == SpaceChar)
829 {
830 int nStartPos = nPos;
831 int nEndPos = nPos+1;
832 while (nStartPos >= 0 && rText.getCodePointAt(nStartPos) == SpaceChar)
833 --nStartPos;
834 while (nEndPos < rText.getLength() && rText.getCodePointAt(nEndPos) == SpaceChar)
835 ++nEndPos;
836 //Get the previous word boundary + the followed space characters
837 if (nStartPos >= 0)
838 {
839 rBound = pBreakIt->xBreak->getWordBoundary( rText, nStartPos, aLocale, nWordType, sal_True );
840 rBound.endPos += (nEndPos-nStartPos - 1);
841 }
842 //When the frontal characters are whitespace, return the all space characters directly.
843 else
844 {
845 rBound.startPos = 0;
846 rBound.endPos = nEndPos;
847 }
848 }
849 // add the " " into the word boundary
850 else
851 {
852 rBound = pBreakIt->xBreak->getWordBoundary(rText, nPos, aLocale, nWordType, sal_True );
853 sal_Int32 nEndPos = rBound.endPos, nLength = rText.getLength();
854 while ( nEndPos < nLength && rText.getCodePointAt(nEndPos) == SpaceChar )
855 nEndPos++;
856 rBound.endPos = nEndPos;
857 }
858 tabCharInWord( nPos, rBound);
859 if( GetPortionData().FillBoundaryIFDateField( rBound, rBound.startPos) )
860 return sal_True;
861 return sal_True; // MT: So why do we need the return TRUE above???
862 */
863 // get word boundary, as the Break-Iterator sees fit.
864 rBound = pBreakIt->GetBreakIter()->getWordBoundary(
865 rText, nPos, aLocale, nWordType, sal_True );
866
867 // It's a word if the first character is an alpha-numeric character.
868 bRet = GetAppCharClass().isLetterNumeric(
869 rText.getStr()[ rBound.startPos ] );
870 }
871 else
872 {
873 // no break Iterator -> no word
874 rBound.startPos = nPos;
875 rBound.endPos = nPos;
876 }
877
878 return bRet;
879 }
880
GetSentenceBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32 nPos)881 sal_Bool SwAccessibleParagraph::GetSentenceBoundary(
882 i18n::Boundary& rBound,
883 const ::rtl::OUString& rText,
884 sal_Int32 nPos )
885 {
886 const sal_Unicode* pStr = rText.getStr();
887 if (pStr)
888 {
889 while( pStr[nPos] == sal_Unicode(' ') && nPos < rText.getLength())
890 nPos++;
891 }
892 GetPortionData().GetSentenceBoundary( rBound, nPos );
893 return sal_True;
894 }
895
GetLineBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32 nPos)896 sal_Bool SwAccessibleParagraph::GetLineBoundary(
897 i18n::Boundary& rBound,
898 const ::rtl::OUString& rText,
899 sal_Int32 nPos )
900 {
901 if( rText.getLength() == nPos )
902 GetPortionData().GetLastLineBoundary( rBound );
903 else
904 GetPortionData().GetLineBoundary( rBound, nPos );
905 return sal_True;
906 }
907
GetParagraphBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32)908 sal_Bool SwAccessibleParagraph::GetParagraphBoundary(
909 i18n::Boundary& rBound,
910 const ::rtl::OUString& rText,
911 sal_Int32 )
912 {
913 rBound.startPos = 0;
914 rBound.endPos = rText.getLength();
915 return sal_True;
916 }
917
GetAttributeBoundary(i18n::Boundary & rBound,const::rtl::OUString &,sal_Int32 nPos)918 sal_Bool SwAccessibleParagraph::GetAttributeBoundary(
919 i18n::Boundary& rBound,
920 const ::rtl::OUString&,
921 sal_Int32 nPos )
922 {
923 GetPortionData().GetAttributeBoundary( rBound, nPos );
924 return sal_True;
925 }
926
GetGlyphBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32 nPos)927 sal_Bool SwAccessibleParagraph::GetGlyphBoundary(
928 i18n::Boundary& rBound,
929 const ::rtl::OUString& rText,
930 sal_Int32 nPos )
931 {
932 sal_Bool bRet = sal_False;
933
934 // ask the Break-Iterator for the glyph by moving one cell
935 // forward, and then one cell back
936 DBG_ASSERT( pBreakIt != NULL, "We always need a break." );
937 DBG_ASSERT( pBreakIt->GetBreakIter().is(), "No break-iterator." );
938 if( pBreakIt->GetBreakIter().is() )
939 {
940 // get locale for this position
941 sal_uInt16 nModelPos = GetPortionData().GetModelPosition( nPos );
942 lang::Locale aLocale = pBreakIt->GetLocale(
943 GetTxtNode()->GetLang( nModelPos ) );
944
945 // get word boundary, as the Break-Iterator sees fit.
946 const sal_uInt16 nIterMode = i18n::CharacterIteratorMode::SKIPCELL;
947 sal_Int32 nDone = 0;
948 rBound.endPos = pBreakIt->GetBreakIter()->nextCharacters(
949 rText, nPos, aLocale, nIterMode, 1, nDone );
950 rBound.startPos = pBreakIt->GetBreakIter()->previousCharacters(
951 rText, rBound.endPos, aLocale, nIterMode, 1, nDone );
952
953 bRet = ((rBound.startPos <= nPos) && (nPos <= rBound.endPos));
954 DBG_ASSERT( rBound.startPos <= nPos, "start pos too high" );
955 DBG_ASSERT( rBound.endPos >= nPos, "end pos too low" );
956 }
957 else
958 {
959 // no break Iterator -> no glyph
960 rBound.startPos = nPos;
961 rBound.endPos = nPos;
962 }
963
964 return bRet;
965 }
966
967
GetTextBoundary(i18n::Boundary & rBound,const::rtl::OUString & rText,sal_Int32 nPos,sal_Int16 nTextType)968 sal_Bool SwAccessibleParagraph::GetTextBoundary(
969 i18n::Boundary& rBound,
970 const ::rtl::OUString& rText,
971 sal_Int32 nPos,
972 sal_Int16 nTextType )
973 throw (
974 lang::IndexOutOfBoundsException,
975 lang::IllegalArgumentException,
976 uno::RuntimeException)
977 {
978 // error checking
979 if( !( AccessibleTextType::LINE == nTextType
980 ? IsValidPosition( nPos, rText.getLength() )
981 : IsValidChar( nPos, rText.getLength() ) ) )
982 throw lang::IndexOutOfBoundsException();
983
984 sal_Bool bRet;
985
986 switch( nTextType )
987 {
988 case AccessibleTextType::WORD:
989 bRet = GetWordBoundary( rBound, rText, nPos );
990 break;
991
992 case AccessibleTextType::SENTENCE:
993 bRet = GetSentenceBoundary( rBound, rText, nPos );
994 break;
995
996 case AccessibleTextType::PARAGRAPH:
997 bRet = GetParagraphBoundary( rBound, rText, nPos );
998 break;
999
1000 case AccessibleTextType::CHARACTER:
1001 bRet = GetCharBoundary( rBound, rText, nPos );
1002 break;
1003
1004 case AccessibleTextType::LINE:
1005 //Solve the problem of returning wrong LINE and PARAGRAPH
1006 if((nPos == rText.getLength()) && nPos > 0)
1007 bRet = GetLineBoundary( rBound, rText, nPos - 1);
1008 else
1009 bRet = GetLineBoundary( rBound, rText, nPos );
1010 break;
1011
1012 case AccessibleTextType::ATTRIBUTE_RUN:
1013 bRet = GetAttributeBoundary( rBound, rText, nPos );
1014 if(bRet)
1015 {
1016 SwCrsrShell* pCrsrShell = GetCrsrShell();
1017 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell())
1018 {
1019 SwTxtNode* pTxtNode = const_cast<SwTxtNode*>( GetTxtNode() );
1020 if(pTxtNode)
1021 {
1022 const SwWrongList* pWrongList = pTxtNode->GetWrong();
1023 if( NULL != pWrongList )
1024 {
1025 xub_StrLen nBegin = nPos;
1026 xub_StrLen nLen = 1;
1027 const xub_StrLen nNext = pWrongList->NextWrong(nBegin);
1028 xub_StrLen nLast;
1029 xub_StrLen nWrongPos = pWrongList->GetWrongPos( nBegin );
1030 if ( nWrongPos >= pWrongList->Count() ||
1031 ( nLast = pWrongList->Pos( nWrongPos ) ) >= nBegin )
1032 {
1033 nLast = nWrongPos
1034 ? pWrongList->Pos( --nWrongPos )
1035 : STRING_LEN;
1036 }
1037 if ( nBegin > pWrongList->GetBeginInv() &&
1038 ( nLast == STRING_LEN || nLast < pWrongList->GetEndInv() ) )
1039 {
1040 nLast = nBegin > pWrongList->GetEndInv()
1041 ? pWrongList->GetEndInv()
1042 : nBegin;
1043 }
1044 else if ( nLast < STRING_LEN )
1045 {
1046 nLast += pWrongList->Len( nWrongPos );
1047 }
1048 //
1049 sal_Bool bIn = pWrongList->InWrongWord(nBegin,nLen); // && !pTxtNode->IsSymbol(nBegin) )
1050 if(bIn)
1051 {
1052 rBound.startPos = max(nNext,(xub_StrLen)rBound.startPos);
1053 rBound.endPos = min(xub_StrLen(nNext + nLen),(xub_StrLen)rBound.endPos);
1054 }
1055 else
1056 {
1057 if (STRING_LEN == nLast)//first
1058 {
1059 rBound.endPos = min(nNext,(xub_StrLen)rBound.endPos);
1060 }
1061 else if(STRING_LEN == nNext)
1062 {
1063 rBound.startPos = max(nLast,(xub_StrLen)rBound.startPos);
1064 }
1065 else
1066 {
1067 rBound.startPos = max(nLast,(xub_StrLen)rBound.startPos);
1068 rBound.endPos = min(nNext,(xub_StrLen)rBound.endPos);
1069 }
1070 }
1071 }
1072 }
1073 }
1074 }
1075 break;
1076
1077 case AccessibleTextType::GLYPH:
1078 bRet = GetGlyphBoundary( rBound, rText, nPos );
1079 break;
1080
1081 default:
1082 throw lang::IllegalArgumentException( );
1083 }
1084
1085 return bRet;
1086 }
1087
getAccessibleDescription(void)1088 ::rtl::OUString SAL_CALL SwAccessibleParagraph::getAccessibleDescription (void)
1089 throw (uno::RuntimeException)
1090 {
1091 vos::OGuard aGuard(Application::GetSolarMutex());
1092
1093 CHECK_FOR_DEFUNC( XAccessibleContext );
1094
1095 vos::OGuard aGuard2( aMutex );
1096 if( !sDesc.getLength() )
1097 sDesc = GetDescription();
1098
1099 return sDesc;
1100 }
1101
getLocale(void)1102 lang::Locale SAL_CALL SwAccessibleParagraph::getLocale (void)
1103 throw (IllegalAccessibleComponentStateException, uno::RuntimeException)
1104 {
1105 vos::OGuard aGuard(Application::GetSolarMutex());
1106
1107 SwTxtFrm *pTxtFrm = PTR_CAST( SwTxtFrm, GetFrm() );
1108 if( !pTxtFrm )
1109 {
1110 THROW_RUNTIME_EXCEPTION( XAccessibleContext, "internal error (no text frame)" );
1111 }
1112
1113 const SwTxtNode *pTxtNd = pTxtFrm->GetTxtNode();
1114 lang::Locale aLoc( pBreakIt->GetLocale( pTxtNd->GetLang( 0 ) ) );
1115
1116 return aLoc;
1117 }
1118
1119 /** paragraphs are in relation CONTENT_FLOWS_FROM and/or CONTENT_FLOWS_TO
1120
1121 OD 2005-12-02 #i27138#
1122
1123 @author OD
1124 */
getAccessibleRelationSet()1125 uno::Reference<XAccessibleRelationSet> SAL_CALL SwAccessibleParagraph::getAccessibleRelationSet()
1126 throw ( uno::RuntimeException )
1127 {
1128 vos::OGuard aGuard(Application::GetSolarMutex());
1129 CHECK_FOR_DEFUNC( XAccessibleContext );
1130
1131 utl::AccessibleRelationSetHelper* pHelper = new utl::AccessibleRelationSetHelper();
1132
1133 const SwTxtFrm* pTxtFrm = dynamic_cast<const SwTxtFrm*>(GetFrm());
1134 ASSERT( pTxtFrm,
1135 "<SwAccessibleParagraph::getAccessibleRelationSet()> - missing text frame");
1136 if ( pTxtFrm )
1137 {
1138 const SwCntntFrm* pPrevCntFrm( pTxtFrm->FindPrevCnt( true ) );
1139 if ( pPrevCntFrm )
1140 {
1141 uno::Sequence< uno::Reference<XInterface> > aSequence(1);
1142 aSequence[0] = GetMap()->GetContext( pPrevCntFrm );
1143 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
1144 aSequence );
1145 pHelper->AddRelation( aAccRel );
1146 }
1147
1148 const SwCntntFrm* pNextCntFrm( pTxtFrm->FindNextCnt( true ) );
1149 if ( pNextCntFrm )
1150 {
1151 uno::Sequence< uno::Reference<XInterface> > aSequence(1);
1152 aSequence[0] = GetMap()->GetContext( pNextCntFrm );
1153 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
1154 aSequence );
1155 pHelper->AddRelation( aAccRel );
1156 }
1157 }
1158
1159 return pHelper;
1160 }
1161
grabFocus()1162 void SAL_CALL SwAccessibleParagraph::grabFocus()
1163 throw (uno::RuntimeException)
1164 {
1165 vos::OGuard aGuard(Application::GetSolarMutex());
1166
1167 CHECK_FOR_DEFUNC( XAccessibleContext );
1168
1169 // get cursor shell
1170 SwCrsrShell *pCrsrSh = GetCrsrShell();
1171 // --> OD 2005-12-20 #i27301# - consider new method signature
1172 SwPaM *pCrsr = GetCursor( false );
1173 // <--
1174 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
1175 const SwTxtNode* pTxtNd = pTxtFrm->GetTxtNode();
1176
1177 if( pCrsrSh != 0 && pTxtNd != 0 &&
1178 ( pCrsr == 0 ||
1179 pCrsr->GetPoint()->nNode.GetIndex() != pTxtNd->GetIndex() ||
1180 !pTxtFrm->IsInside( pCrsr->GetPoint()->nContent.GetIndex()) ) )
1181 {
1182 // create pam for selection
1183 SwIndex aIndex( const_cast< SwTxtNode * >( pTxtNd ),
1184 pTxtFrm->GetOfst() );
1185 SwPosition aStartPos( *pTxtNd, aIndex );
1186 SwPaM aPaM( aStartPos );
1187
1188 // set PaM at cursor shell
1189 Select( aPaM );
1190
1191
1192 }
1193
1194 /* ->#i13955# */
1195 Window * pWindow = GetWindow();
1196
1197 if (pWindow != NULL)
1198 pWindow->GrabFocus();
1199 /* <-#i13955# */
1200 }
1201
1202 // --> OD 2007-01-17 #i71385#
lcl_GetBackgroundColor(Color & rColor,const SwFrm * pFrm,SwCrsrShell * pCrsrSh)1203 bool lcl_GetBackgroundColor( Color & rColor,
1204 const SwFrm* pFrm,
1205 SwCrsrShell* pCrsrSh )
1206 {
1207 const SvxBrushItem* pBackgrdBrush = 0;
1208 const Color* pSectionTOXColor = 0;
1209 SwRect aDummyRect;
1210
1211 //UUUU
1212 drawinglayer::attribute::SdrAllFillAttributesHelperPtr aFillAttributes;
1213
1214 if ( pFrm &&
1215 pFrm->GetBackgroundBrush( aFillAttributes, pBackgrdBrush, pSectionTOXColor, aDummyRect, false ) )
1216 {
1217 if ( pSectionTOXColor )
1218 {
1219 rColor = *pSectionTOXColor;
1220 return true;
1221 }
1222 else
1223 {
1224 rColor = pBackgrdBrush->GetColor();
1225 return true;
1226 }
1227 }
1228 else if ( pCrsrSh )
1229 {
1230 rColor = pCrsrSh->Imp()->GetRetoucheColor();
1231 return true;
1232 }
1233
1234 return false;
1235 }
1236
getForeground()1237 sal_Int32 SAL_CALL SwAccessibleParagraph::getForeground()
1238 throw (uno::RuntimeException)
1239 {
1240 Color aBackgroundCol;
1241
1242 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
1243 {
1244 if ( aBackgroundCol.IsDark() )
1245 {
1246 return COL_WHITE;
1247 }
1248 else
1249 {
1250 return COL_BLACK;
1251 }
1252 }
1253
1254 return SwAccessibleContext::getForeground();
1255 }
1256
getBackground()1257 sal_Int32 SAL_CALL SwAccessibleParagraph::getBackground()
1258 throw (uno::RuntimeException)
1259 {
1260 Color aBackgroundCol;
1261
1262 if ( lcl_GetBackgroundColor( aBackgroundCol, GetFrm(), GetCrsrShell() ) )
1263 {
1264 return aBackgroundCol.GetColor();
1265 }
1266
1267 return SwAccessibleContext::getBackground();
1268 }
1269 // <--
1270
getImplementationName()1271 ::rtl::OUString SAL_CALL SwAccessibleParagraph::getImplementationName()
1272 throw( uno::RuntimeException )
1273 {
1274 return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(sImplementationName));
1275 }
1276
supportsService(const::rtl::OUString & sTestServiceName)1277 sal_Bool SAL_CALL SwAccessibleParagraph::supportsService(
1278 const ::rtl::OUString& sTestServiceName)
1279 throw (uno::RuntimeException)
1280 {
1281 return sTestServiceName.equalsAsciiL( sServiceName,
1282 sizeof(sServiceName)-1 ) ||
1283 sTestServiceName.equalsAsciiL( sAccessibleServiceName,
1284 sizeof(sAccessibleServiceName)-1 );
1285 }
1286
getSupportedServiceNames()1287 uno::Sequence< ::rtl::OUString > SAL_CALL SwAccessibleParagraph::getSupportedServiceNames()
1288 throw( uno::RuntimeException )
1289 {
1290 uno::Sequence< ::rtl::OUString > aRet(2);
1291 ::rtl::OUString* pArray = aRet.getArray();
1292 pArray[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sServiceName) );
1293 pArray[1] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(sAccessibleServiceName) );
1294 return aRet;
1295 }
1296
getAttributeNames()1297 uno::Sequence< ::rtl::OUString > getAttributeNames()
1298 {
1299 static uno::Sequence< ::rtl::OUString >* pNames = NULL;
1300
1301 if( pNames == NULL )
1302 {
1303 // Add the font name to attribute list
1304 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 13 );
1305
1306 ::rtl::OUString* pStrings = pSeq->getArray();
1307
1308 // sorted list of strings
1309 sal_Int32 i = 0;
1310
1311 #define STR(x) pStrings[i++] = OUString::createFromAscii(x)
1312 STR( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName );
1313 STR( GetPropName( UNO_NAME_CHAR_COLOR ).pName );
1314 STR( GetPropName( UNO_NAME_CHAR_CONTOURED ).pName );
1315 STR( GetPropName( UNO_NAME_CHAR_EMPHASIS ).pName );
1316 STR( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName );
1317 STR( GetPropName( UNO_NAME_CHAR_FONT_NAME ).pName );
1318 STR( GetPropName( UNO_NAME_CHAR_HEIGHT ).pName );
1319 STR( GetPropName( UNO_NAME_CHAR_POSTURE ).pName );
1320 STR( GetPropName( UNO_NAME_CHAR_SHADOWED ).pName );
1321 STR( GetPropName( UNO_NAME_CHAR_STRIKEOUT ).pName );
1322 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName );
1323 STR( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName );
1324 STR( GetPropName( UNO_NAME_CHAR_WEIGHT ).pName );
1325 #undef STR
1326 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" );
1327 if( i != pSeq->getLength() )
1328 pSeq->realloc( i );
1329 pNames = pSeq;
1330 }
1331 return *pNames;
1332 }
1333
getSupplementalAttributeNames()1334 uno::Sequence< ::rtl::OUString > getSupplementalAttributeNames()
1335 {
1336 static uno::Sequence< ::rtl::OUString >* pNames = NULL;
1337
1338 if( pNames == NULL )
1339 {
1340 uno::Sequence< ::rtl::OUString >* pSeq = new uno::Sequence< ::rtl::OUString >( 9 );
1341
1342 ::rtl::OUString* pStrings = pSeq->getArray();
1343
1344 // sorted list of strings
1345 sal_Int32 i = 0;
1346
1347 #define STR(x) pStrings[i++] = OUString::createFromAscii(x)
1348 STR( GetPropName( UNO_NAME_NUMBERING_LEVEL ).pName );
1349 STR( GetPropName( UNO_NAME_NUMBERING_RULES ).pName );
1350 STR( GetPropName( UNO_NAME_PARA_ADJUST ).pName );
1351 STR( GetPropName( UNO_NAME_PARA_BOTTOM_MARGIN ).pName );
1352 STR( GetPropName( UNO_NAME_PARA_FIRST_LINE_INDENT ).pName );
1353 STR( GetPropName( UNO_NAME_PARA_LEFT_MARGIN ).pName );
1354 STR( GetPropName( UNO_NAME_PARA_LINE_SPACING ).pName );
1355 STR( GetPropName( UNO_NAME_PARA_RIGHT_MARGIN ).pName );
1356 STR( GetPropName( UNO_NAME_TABSTOPS ).pName );
1357 #undef STR
1358 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" );
1359 if( i != pSeq->getLength() )
1360 pSeq->realloc( i );
1361 pNames = pSeq;
1362 }
1363 return *pNames;
1364 }
1365 //
1366 //===== XInterface =======================================================
1367 //
1368
queryInterface(const uno::Type & rType)1369 uno::Any SwAccessibleParagraph::queryInterface( const uno::Type& rType )
1370 throw (uno::RuntimeException)
1371 {
1372 uno::Any aRet;
1373 if ( rType == ::getCppuType((uno::Reference<XAccessibleText> *)0) )
1374 {
1375 uno::Reference<XAccessibleText> aAccText = (XAccessibleText *) *this; // resolve ambiguity
1376 aRet <<= aAccText;
1377 }
1378 else if ( rType == ::getCppuType((uno::Reference<XAccessibleEditableText> *)0) )
1379 {
1380 uno::Reference<XAccessibleEditableText> aAccEditText = this;
1381 aRet <<= aAccEditText;
1382 }
1383 else if ( rType == ::getCppuType((uno::Reference<XAccessibleSelection> *)0) )
1384 {
1385 uno::Reference<XAccessibleSelection> aAccSel = this;
1386 aRet <<= aAccSel;
1387 }
1388 else if ( rType == ::getCppuType((uno::Reference<XAccessibleHypertext> *)0) )
1389 {
1390 uno::Reference<XAccessibleHypertext> aAccHyp = this;
1391 aRet <<= aAccHyp;
1392 }
1393 // --> OD 2006-07-13 #i63870#
1394 // add interface com::sun:star:accessibility::XAccessibleTextAttributes
1395 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextAttributes> *)0) )
1396 {
1397 uno::Reference<XAccessibleTextAttributes> aAccTextAttr = this;
1398 aRet <<= aAccTextAttr;
1399 }
1400 // <--
1401 // --> OD 2008-06-10 #i89175#
1402 // add interface com::sun:star:accessibility::XAccessibleTextMarkup
1403 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextMarkup> *)0) )
1404 {
1405 uno::Reference<XAccessibleTextMarkup> aAccTextMarkup = this;
1406 aRet <<= aAccTextMarkup;
1407 }
1408 // add interface com::sun:star:accessibility::XAccessibleMultiLineText
1409 else if ( rType == ::getCppuType((uno::Reference<XAccessibleMultiLineText> *)0) )
1410 {
1411 uno::Reference<XAccessibleMultiLineText> aAccMultiLineText = this;
1412 aRet <<= aAccMultiLineText;
1413 }
1414 // <--
1415 //MSAA Extension Implementation in app module
1416 else if ( rType == ::getCppuType((uno::Reference<XAccessibleTextSelection> *)NULL) )
1417 {
1418 uno::Reference< com::sun::star::accessibility::XAccessibleTextSelection > aTextExtension = this;
1419 aRet <<= aTextExtension;
1420 }
1421 else if ( rType == ::getCppuType((uno::Reference<XAccessibleExtendedAttributes> *)NULL) )
1422 {
1423 uno::Reference<XAccessibleExtendedAttributes> xAttr = this;
1424 aRet <<= xAttr;
1425 }
1426 else
1427 {
1428 aRet = SwAccessibleContext::queryInterface(rType);
1429 }
1430
1431 return aRet;
1432 }
1433
1434 //====== XTypeProvider ====================================================
getTypes()1435 uno::Sequence< uno::Type > SAL_CALL SwAccessibleParagraph::getTypes() throw(uno::RuntimeException)
1436 {
1437 uno::Sequence< uno::Type > aTypes( SwAccessibleContext::getTypes() );
1438
1439 sal_Int32 nIndex = aTypes.getLength();
1440 // --> OD 2006-07-13 #i63870#
1441 // add type accessibility::XAccessibleTextAttributes
1442 // --> OD 2008-06-10 #i89175#
1443 // add type accessibility::XAccessibleTextMarkup and accessibility::XAccessibleMultiLineText
1444 aTypes.realloc( nIndex + 6 );
1445
1446 uno::Type* pTypes = aTypes.getArray();
1447 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleEditableText > * >( 0 ) );
1448 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextAttributes > * >( 0 ) );
1449 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleSelection > * >( 0 ) );
1450 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleTextMarkup > * >( 0 ) );
1451 pTypes[nIndex++] = ::getCppuType( static_cast< uno::Reference< XAccessibleMultiLineText > * >( 0 ) );
1452 pTypes[nIndex] = ::getCppuType( static_cast< uno::Reference< XAccessibleHypertext > * >( 0 ) );
1453 // <--
1454
1455 return aTypes;
1456 }
1457
getImplementationId()1458 uno::Sequence< sal_Int8 > SAL_CALL SwAccessibleParagraph::getImplementationId()
1459 throw(uno::RuntimeException)
1460 {
1461 vos::OGuard aGuard(Application::GetSolarMutex());
1462 static uno::Sequence< sal_Int8 > aId( 16 );
1463 static sal_Bool bInit = sal_False;
1464 if(!bInit)
1465 {
1466 rtl_createUuid( (sal_uInt8 *)(aId.getArray() ), 0, sal_True );
1467 bInit = sal_True;
1468 }
1469 return aId;
1470 }
1471
1472
1473 //
1474 //===== XAccesibleText ===================================================
1475 //
1476
getCaretPosition()1477 sal_Int32 SwAccessibleParagraph::getCaretPosition()
1478 throw (uno::RuntimeException)
1479 {
1480 vos::OGuard aGuard(Application::GetSolarMutex());
1481
1482 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1483
1484 sal_Int32 nRet = GetCaretPos();
1485 {
1486 vos::OGuard aOldCaretPosGuard( aMutex );
1487 ASSERT( nRet == nOldCaretPos, "caret pos out of sync" );
1488 nOldCaretPos = nRet;
1489 }
1490 if( -1 != nRet )
1491 {
1492 ::vos::ORef < SwAccessibleContext > xThis( this );
1493 GetMap()->SetCursorContext( xThis );
1494 }
1495
1496 return nRet;
1497 }
1498
setCaretPosition(sal_Int32 nIndex)1499 sal_Bool SAL_CALL SwAccessibleParagraph::setCaretPosition( sal_Int32 nIndex )
1500 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1501 {
1502 vos::OGuard aGuard(Application::GetSolarMutex());
1503
1504 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1505
1506 // parameter checking
1507 sal_Int32 nLength = GetString().getLength();
1508 if ( ! IsValidPosition( nIndex, nLength ) )
1509 {
1510 throw lang::IndexOutOfBoundsException();
1511 }
1512
1513 sal_Bool bRet = sal_False;
1514
1515 // get cursor shell
1516 SwCrsrShell* pCrsrShell = GetCrsrShell();
1517 if( pCrsrShell != NULL )
1518 {
1519 // create pam for selection
1520 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1521 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nIndex));
1522 SwPosition aStartPos( *pNode, aIndex );
1523 SwPaM aPaM( aStartPos );
1524
1525 // set PaM at cursor shell
1526 bRet = Select( aPaM );
1527 }
1528
1529 return bRet;
1530 }
1531
getCharacter(sal_Int32 nIndex)1532 sal_Unicode SwAccessibleParagraph::getCharacter( sal_Int32 nIndex )
1533 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1534 {
1535 vos::OGuard aGuard(Application::GetSolarMutex());
1536
1537 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1538
1539 ::rtl::OUString sText( GetString() );
1540
1541 // return character (if valid)
1542 if( IsValidChar(nIndex, sText.getLength() ) )
1543 {
1544 return sText.getStr()[nIndex];
1545 }
1546 else
1547 throw lang::IndexOutOfBoundsException();
1548 }
1549
GetCurrentTabStop(sal_Int32 nIndex)1550 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > SwAccessibleParagraph::GetCurrentTabStop( sal_Int32 nIndex )
1551 {
1552 vos::OGuard aGuard(Application::GetSolarMutex());
1553 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1554
1555
1556
1557 /* #i12332# The position after the string needs special treatment.
1558 IsValidChar -> IsValidPosition
1559 */
1560 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
1561 throw lang::IndexOutOfBoundsException();
1562
1563 /* #i12332# */
1564 sal_Bool bBehindText = sal_False;
1565 if ( nIndex == GetString().getLength() )
1566 bBehindText = sal_True;
1567
1568 // get model position & prepare GetCharRect() arguments
1569 SwCrsrMoveState aMoveState;
1570 aMoveState.bRealHeight = sal_True;
1571 aMoveState.bRealWidth = sal_True;
1572 SwSpecialPos aSpecialPos;
1573 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
1574
1575 sal_uInt16 nPos = 0;
1576
1577 /* #i12332# FillSpecialPos does not accept nIndex ==
1578 GetString().getLength(). In that case nPos is set to the
1579 length of the string in the core. This way GetCharRect
1580 returns the rectangle for a cursor at the end of the
1581 paragraph. */
1582 if (bBehindText)
1583 {
1584 nPos = pNode->GetTxt().Len();
1585 }
1586 else
1587 nPos = GetPortionData().FillSpecialPos
1588 (nIndex, aSpecialPos, aMoveState.pSpecialPos );
1589
1590 // call GetCharRect
1591 SwRect aCoreRect;
1592 SwIndex aIndex( pNode, nPos );
1593 SwPosition aPosition( *pNode, aIndex );
1594 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
1595
1596 // already get the caret position
1597
1598 /*SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm());
1599 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs =
1600 pTFrm->GetTabStopInfo(aCoreRect.Left());*/
1601
1602 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs;
1603 const xub_StrLen nStrLen = GetTxtNode()->GetTxt().Len();
1604 if( nStrLen > 0 )
1605 {
1606 SwFrm* pTFrm = const_cast<SwFrm*>(GetFrm());
1607 tabs = pTFrm->GetTabStopInfo(aCoreRect.Left());
1608 }
1609
1610 if( tabs.hasElements() )
1611 {
1612 // translate core coordinates into accessibility coordinates
1613 Window *pWin = GetWindow();
1614 CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
1615
1616 SwRect aTmpRect(0, 0, tabs[0].Position, 0);
1617
1618 Rectangle aScreenRect( GetMap()->CoreToPixel( aTmpRect.SVRect() ));
1619 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
1620
1621 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
1622 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
1623
1624 tabs[0].Position = aScreenRect.GetWidth();
1625 }
1626
1627 return tabs;
1628 }
1629
1630 struct IndexCompare
1631 {
1632 const PropertyValue* pValues;
IndexCompareIndexCompare1633 IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
operator ()IndexCompare1634 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
1635 {
1636 return (pValues[a].Name < pValues[b].Name) ? true : false;
1637 }
1638 };
1639
GetFieldTypeNameAtIndex(sal_Int32 nIndex)1640 String SwAccessibleParagraph::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
1641 {
1642 String strTypeName;
1643 SwFldMgr aMgr;
1644 SwTxtFld* pTxtFld = NULL;
1645 SwTxtNode* pTxtNd = const_cast<SwTxtNode*>( GetTxtNode() );
1646 SwIndex fldIndex( pTxtNd, nIndex );
1647 sal_Int32 nFldIndex = GetPortionData().GetFieldIndex(nIndex);
1648 if (nFldIndex >= 0)
1649 {
1650 const SwpHints* pSwpHints = GetTxtNode()->GetpSwpHints();
1651 if (pSwpHints)
1652 {
1653 const sal_uInt16 nSize = pSwpHints ? pSwpHints->Count() : 0;
1654 for( sal_uInt16 i = 0; i < nSize; ++i )
1655 {
1656 const SwTxtAttr* pHt = (*pSwpHints)[i];
1657 if ( ( pHt->Which() == RES_TXTATR_FIELD
1658 || pHt->Which() == RES_TXTATR_ANNOTATION
1659 || pHt->Which() == RES_TXTATR_INPUTFIELD )
1660 && (nFldIndex-- == 0))
1661 {
1662 pTxtFld = (SwTxtFld *)pHt;
1663 break;
1664 }
1665 else if ( pHt->Which() == RES_TXTATR_REFMARK
1666 && (nFldIndex-- == 0) )
1667 strTypeName = String(OUString(RTL_CONSTASCII_USTRINGPARAM("set reference")));
1668 }
1669 }
1670 }
1671 if (pTxtFld)
1672 {
1673 const SwField* pField = (pTxtFld->GetFmtFld()).GetField();
1674 if (pField)
1675 {
1676 strTypeName = pField->GetTyp()->GetTypeStr(pField->GetTypeId());
1677 sal_uInt16 nWhich = pField->GetTyp()->Which();
1678 rtl::OUString sEntry;
1679 sal_Int32 subType = 0;
1680 switch (nWhich)
1681 {
1682 case RES_DOCSTATFLD:
1683 subType = ((SwDocStatField*)pField)->GetSubType();
1684 break;
1685 case RES_GETREFFLD:
1686 {
1687 sal_uInt16 nSub = pField->GetSubType();
1688 switch( nSub )
1689 {
1690 case REF_BOOKMARK:
1691 {
1692 const SwGetRefField* pRefFld = dynamic_cast<const SwGetRefField*>(pField);
1693 if ( pRefFld && pRefFld->IsRefToHeadingCrossRefBookmark() )
1694 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Headings"));
1695 else if ( pRefFld && pRefFld->IsRefToNumItemCrossRefBookmark() )
1696 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Numbered Paragraphs"));
1697 else
1698 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Bookmarks"));
1699 }
1700 break;
1701 case REF_FOOTNOTE:
1702 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Footnotes"));
1703 break;
1704 case REF_ENDNOTE:
1705 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Endnotes"));
1706 break;
1707 case REF_SETREFATTR:
1708 sEntry = OUString(RTL_CONSTASCII_USTRINGPARAM("Insert Reference"));
1709 break;
1710 case REF_SEQUENCEFLD:
1711 sEntry = ((SwGetRefField*)pField)->GetSetRefName();
1712 break;
1713 }
1714 //Get format string
1715 strTypeName = sEntry;
1716 // <pField->GetFormat() >= 0> is always true as <pField->GetFormat()> is unsigned
1717 // if (pField->GetFormat() >= 0)
1718 {
1719 sEntry = aMgr.GetFormatStr( pField->GetTypeId(), pField->GetFormat() );
1720 if (sEntry.getLength() > 0)
1721 {
1722 strTypeName.AppendAscii("-");
1723 strTypeName += String(sEntry);
1724 }
1725 }
1726 }
1727 break;
1728 case RES_DATETIMEFLD:
1729 subType = ((SwDateTimeField*)pField)->GetSubType();
1730 break;
1731 case RES_JUMPEDITFLD:
1732 {
1733 sal_uInt16 nFormat= pField->GetFormat();
1734 sal_uInt16 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False);
1735 if (nFormat < nSize)
1736 {
1737 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nFormat);
1738 if (sEntry.getLength() > 0)
1739 {
1740 strTypeName.AppendAscii("-");
1741 strTypeName += String(sEntry);
1742 }
1743 }
1744 }
1745 break;
1746 case RES_EXTUSERFLD:
1747 subType = ((SwExtUserField*)pField)->GetSubType();
1748 break;
1749 case RES_HIDDENTXTFLD:
1750 case RES_SETEXPFLD:
1751 {
1752 sEntry = pField->GetTyp()->GetName();
1753 if (sEntry.getLength() > 0)
1754 {
1755 strTypeName.AppendAscii("-");
1756 strTypeName += String(sEntry);
1757 }
1758 }
1759 break;
1760 case RES_DOCINFOFLD:
1761 subType = pField->GetSubType();
1762 subType &= 0x00ff;
1763 break;
1764 case RES_REFPAGESETFLD:
1765 {
1766 SwRefPageSetField* pRPld = (SwRefPageSetField*)pField;
1767 sal_Bool bOn = pRPld->IsOn();
1768 strTypeName.AppendAscii("-");
1769 if (bOn)
1770 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("on")));
1771 else
1772 strTypeName += String(OUString(RTL_CONSTASCII_USTRINGPARAM("off")));
1773 }
1774 break;
1775 case RES_AUTHORFLD:
1776 {
1777 strTypeName.AppendAscii("-");
1778 strTypeName += aMgr.GetFormatStr(pField->GetTypeId(), pField->GetFormat() & 0xff);
1779 }
1780 break;
1781 }
1782 if (subType > 0 || (subType == 0 && (nWhich == RES_DOCINFOFLD || nWhich == RES_EXTUSERFLD || nWhich == RES_DOCSTATFLD)))
1783 {
1784 SvStringsDtor aLst;
1785 aMgr.GetSubTypes(pField->GetTypeId(), aLst);
1786 if (subType < aLst.Count())
1787 sEntry = *aLst[subType];
1788 if (sEntry.getLength() > 0)
1789 {
1790 if (nWhich == RES_DOCINFOFLD)
1791 {
1792 strTypeName = String(sEntry);
1793 sal_uInt32 nSize = aMgr.GetFormatCount(pField->GetTypeId(), sal_False);
1794 sal_uInt16 nExSub = pField->GetSubType() & 0xff00;
1795 if (nSize > 0 && nExSub > 0)
1796 {
1797 //Get extra subtype string
1798 strTypeName.AppendAscii("-");
1799 sEntry = aMgr.GetFormatStr(pField->GetTypeId(), nExSub/0x0100-1);
1800 strTypeName += String(sEntry);
1801 }
1802 }
1803 else
1804 {
1805 strTypeName.AppendAscii("-");
1806 strTypeName += String(sEntry);
1807 }
1808 }
1809 }
1810 }
1811 }
1812 return strTypeName;
1813 }
1814 // --> OD 2006-07-20 #i63870#
1815 // re-implement method on behalf of methods <_getDefaultAttributesImpl(..)> and
1816 // <_getRunAttributesImpl(..)>
getCharacterAttributes(sal_Int32 nIndex,const uno::Sequence<::rtl::OUString> & aRequestedAttributes)1817 uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
1818 sal_Int32 nIndex,
1819 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
1820 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
1821 {
1822
1823 vos::OGuard aGuard(Application::GetSolarMutex());
1824 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
1825
1826 const ::rtl::OUString& rText = GetString();
1827
1828 if( ! IsValidChar( nIndex, rText.getLength()+1 ) )
1829 throw lang::IndexOutOfBoundsException();
1830
1831 bool bSupplementalMode = false;
1832 uno::Sequence< ::rtl::OUString > aNames = aRequestedAttributes;
1833 if (aNames.getLength() == 0)
1834 {
1835 bSupplementalMode = true;
1836 aNames = getAttributeNames();
1837 }
1838 // retrieve default character attributes
1839 tAccParaPropValMap aDefAttrSeq;
1840 _getDefaultAttributesImpl( aNames, aDefAttrSeq, true );
1841
1842 // retrieved run character attributes
1843 tAccParaPropValMap aRunAttrSeq;
1844 _getRunAttributesImpl( nIndex, aNames, aRunAttrSeq );
1845
1846 // merge default and run attributes
1847 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() );
1848 PropertyValue* pValues = aValues.getArray();
1849 sal_Int32 i = 0;
1850 for ( tAccParaPropValMap::const_iterator aDefIter = aDefAttrSeq.begin();
1851 aDefIter != aDefAttrSeq.end();
1852 ++aDefIter )
1853 {
1854 tAccParaPropValMap::const_iterator aRunIter =
1855 aRunAttrSeq.find( aDefIter->first );
1856 if ( aRunIter != aRunAttrSeq.end() )
1857 {
1858 pValues[i] = aRunIter->second;
1859 }
1860 else
1861 {
1862 pValues[i] = aDefIter->second;
1863 }
1864 ++i;
1865 }
1866 if( bSupplementalMode )
1867 {
1868 uno::Sequence< ::rtl::OUString > aSupplementalNames = aRequestedAttributes;
1869 if (aSupplementalNames.getLength() == 0)
1870 aSupplementalNames = getSupplementalAttributeNames();
1871
1872 tAccParaPropValMap aSupplementalAttrSeq;
1873 _getSupplementalAttributesImpl( nIndex, aSupplementalNames, aSupplementalAttrSeq );
1874
1875 aValues.realloc( aValues.getLength() + aSupplementalAttrSeq.size() );
1876 pValues = aValues.getArray();
1877
1878 for ( tAccParaPropValMap::const_iterator aSupplementalIter = aSupplementalAttrSeq.begin();
1879 aSupplementalIter != aSupplementalAttrSeq.end();
1880 ++aSupplementalIter )
1881 {
1882 pValues[i] = aSupplementalIter->second;
1883 ++i;
1884 }
1885
1886 _correctValues( nIndex, aValues );
1887
1888 aValues.realloc( aValues.getLength() + 1 );
1889
1890 pValues = aValues.getArray();
1891
1892 const SwTxtNode* pTxtNode( GetTxtNode() );
1893 PropertyValue& rValue = pValues[aValues.getLength() - 1 ];
1894 rValue.Name = OUString::createFromAscii("NumberingPrefix");
1895 OUString sNumBullet = pTxtNode->GetNumString();
1896 rValue.Value <<= sNumBullet;
1897 rValue.Handle = -1;
1898 rValue.State = PropertyState_DIRECT_VALUE;
1899
1900 String strTypeName = GetFieldTypeNameAtIndex(nIndex);
1901 if (strTypeName.Len() > 0)
1902 {
1903 aValues.realloc( aValues.getLength() + 1 );
1904 pValues = aValues.getArray();
1905 PropertyValue& rValueFT = pValues[aValues.getLength() - 1];
1906 rValueFT.Name = OUString::createFromAscii("FieldType");
1907 rValueFT.Value <<= rtl::OUString(strTypeName.ToLowerAscii());
1908 rValueFT.Handle = -1;
1909 rValueFT.State = PropertyState_DIRECT_VALUE;
1910 }
1911
1912 //sort property values
1913 // build sorted index array
1914 sal_Int32 nLength = aValues.getLength();
1915 const PropertyValue* pPairs = aValues.getConstArray();
1916 sal_Int32* pIndices = new sal_Int32[nLength];
1917 for( i = 0; i < nLength; i++ )
1918 pIndices[i] = i;
1919 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
1920 // create sorted sequences according to index array
1921 uno::Sequence<PropertyValue> aNewValues( nLength );
1922 PropertyValue* pNewValues = aNewValues.getArray();
1923 for( i = 0; i < nLength; i++ )
1924 {
1925 pNewValues[i] = pPairs[pIndices[i]];
1926 }
1927 delete[] pIndices;
1928 return aNewValues;
1929 }
1930
1931 // // create a (dummy) text portion for the sole purpose of calling
1932 // // getPropertyValues on it
1933 // Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nIndex, nIndex + 1 );
1934
1935 // // get values
1936 // Sequence<OUString> aNames = getAttributeNames();
1937 // sal_Int32 nLength = aNames.getLength();
1938 // Sequence<Any> aAnys( nLength );
1939 // aAnys = xPortion->getPropertyValues( aNames );
1940
1941 // // copy names + anys into return sequence
1942 // Sequence<PropertyValue> aValues( aNames.getLength() );
1943 // const OUString* pNames = aNames.getConstArray();
1944 // const Any* pAnys = aAnys.getConstArray();
1945 // PropertyValue* pValues = aValues.getArray();
1946 // for( sal_Int32 i = 0; i < nLength; i++ )
1947 // {
1948 // PropertyValue& rValue = pValues[i];
1949 // rValue.Name = pNames[i];
1950 // rValue.Value = pAnys[i];
1951 // rValue.Handle = -1; // handle not supported
1952 // rValue.State = PropertyState_DIRECT_VALUE; // states not supported
1953 // }
1954
1955 // // adjust background color if we're in a gray portion
1956 // DBG_ASSERT( pValues[CHAR_BACK_COLOR_POS].Name.
1957 // equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("CharBackColor")),
1958 // "Please adjust CHAR_BACK_COLOR_POS constant." );
1959 // if( GetPortionData().IsInGrayPortion( nIndex ) )
1960 // pValues[CHAR_BACK_COLOR_POS].Value <<= SwViewOption::GetFieldShadingsColor().GetColor();
1961
1962 return aValues;
1963 }
1964
1965 // --> OD 2006-07-11 #i63870#
_getDefaultAttributesImpl(const uno::Sequence<::rtl::OUString> & aRequestedAttributes,tAccParaPropValMap & rDefAttrSeq,const bool bOnlyCharAttrs)1966 void SwAccessibleParagraph::_getDefaultAttributesImpl(
1967 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
1968 tAccParaPropValMap& rDefAttrSeq,
1969 const bool bOnlyCharAttrs )
1970 {
1971 // retrieve default attributes
1972 const SwTxtNode* pTxtNode( GetTxtNode() );
1973 ::boost::scoped_ptr<SfxItemSet> pSet;
1974 if ( !bOnlyCharAttrs )
1975 {
1976 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1977 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1978 RES_PARATR_BEGIN, RES_PARATR_END - 1,
1979 RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
1980 0 ) );
1981 }
1982 else
1983 {
1984 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1985 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
1986 0 ) );
1987 }
1988 // --> OD 2007-11-12 #i82637#
1989 // From the perspective of the a11y API the default character attributes
1990 // are the character attributes, which are set at the paragraph style
1991 // of the paragraph. The character attributes set at the automatic paragraph
1992 // style of the paragraph are treated as run attributes.
1993 // pTxtNode->SwCntntNode::GetAttr( *pSet );
1994 // get default paragraph attributes, if needed, and merge these into <pSet>
1995 if ( !bOnlyCharAttrs )
1996 {
1997 SfxItemSet aParaSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
1998 RES_PARATR_BEGIN, RES_PARATR_END - 1,
1999 RES_FRMATR_BEGIN, RES_FRMATR_END - 1,
2000 0 );
2001 pTxtNode->SwCntntNode::GetAttr( aParaSet );
2002 pSet->Put( aParaSet );
2003 }
2004 // get default character attributes and merge these into <pSet>
2005 ASSERT( pTxtNode->GetTxtColl(),
2006 "<SwAccessibleParagraph::_getDefaultAttributesImpl(..)> - missing paragraph style. Serious defect, please inform OD!" );
2007 if ( pTxtNode->GetTxtColl() )
2008 {
2009 SfxItemSet aCharSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
2010 RES_CHRATR_BEGIN, RES_CHRATR_END - 1,
2011 0 );
2012 aCharSet.Put( pTxtNode->GetTxtColl()->GetAttrSet() );
2013 pSet->Put( aCharSet );
2014 }
2015 // <--
2016
2017 // build-up sequence containing the run attributes <rDefAttrSeq>
2018 tAccParaPropValMap aDefAttrSeq;
2019 {
2020 const SfxItemPropertyMap* pPropMap =
2021 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
2022 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
2023 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
2024 while ( aPropIt != aPropertyEntries.end() )
2025 {
2026 const SfxPoolItem* pItem = pSet->GetItem( aPropIt->nWID );
2027 if ( pItem )
2028 {
2029 uno::Any aVal;
2030 pItem->QueryValue( aVal, aPropIt->nMemberId );
2031
2032 PropertyValue rPropVal;
2033 rPropVal.Name = aPropIt->sName;
2034 rPropVal.Value = aVal;
2035 rPropVal.Handle = -1;
2036 rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
2037
2038 aDefAttrSeq[rPropVal.Name] = rPropVal;
2039 }
2040 ++aPropIt;
2041 }
2042
2043 // --> OD 2007-01-15 #i72800#
2044 // add property value entry for the paragraph style
2045 if ( !bOnlyCharAttrs && pTxtNode->GetTxtColl() )
2046 {
2047 const ::rtl::OUString sParaStyleName =
2048 ::rtl::OUString::createFromAscii(
2049 GetPropName( UNO_NAME_PARA_STYLE_NAME ).pName );
2050 if ( aDefAttrSeq.find( sParaStyleName ) == aDefAttrSeq.end() )
2051 {
2052 PropertyValue rPropVal;
2053 rPropVal.Name = sParaStyleName;
2054 uno::Any aVal( uno::makeAny( ::rtl::OUString( pTxtNode->GetTxtColl()->GetName() ) ) );
2055 rPropVal.Value = aVal;
2056 rPropVal.Handle = -1;
2057 rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
2058
2059 aDefAttrSeq[rPropVal.Name] = rPropVal;
2060 }
2061 }
2062 // <--
2063
2064 // --> OD 2007-01-15 #i73371#
2065 // resolve value text::WritingMode2::PAGE of property value entry WritingMode
2066 if ( !bOnlyCharAttrs && GetFrm() )
2067 {
2068 const ::rtl::OUString sWritingMode =
2069 ::rtl::OUString::createFromAscii(
2070 GetPropName( UNO_NAME_WRITING_MODE ).pName );
2071 tAccParaPropValMap::iterator aIter = aDefAttrSeq.find( sWritingMode );
2072 if ( aIter != aDefAttrSeq.end() )
2073 {
2074 PropertyValue rPropVal( aIter->second );
2075 sal_Int16 nVal = rPropVal.Value.get<sal_Int16>();
2076 if ( nVal == text::WritingMode2::PAGE )
2077 {
2078 const SwFrm* pUpperFrm( GetFrm()->GetUpper() );
2079 while ( pUpperFrm )
2080 {
2081 if ( pUpperFrm->GetType() &
2082 ( FRM_PAGE | FRM_FLY | FRM_SECTION | FRM_TAB | FRM_CELL ) )
2083 {
2084 if ( pUpperFrm->IsVertical() )
2085 {
2086 nVal = text::WritingMode2::TB_RL;
2087 }
2088 else if ( pUpperFrm->IsRightToLeft() )
2089 {
2090 nVal = text::WritingMode2::RL_TB;
2091 }
2092 else
2093 {
2094 nVal = text::WritingMode2::LR_TB;
2095 }
2096 rPropVal.Value <<= nVal;
2097 aDefAttrSeq[rPropVal.Name] = rPropVal;
2098 break;
2099 }
2100
2101 if ( dynamic_cast<const SwFlyFrm*>(pUpperFrm) )
2102 {
2103 pUpperFrm = dynamic_cast<const SwFlyFrm*>(pUpperFrm)->GetAnchorFrm();
2104 }
2105 else
2106 {
2107 pUpperFrm = pUpperFrm->GetUpper();
2108 }
2109 }
2110 }
2111 }
2112 }
2113 // <--
2114 }
2115
2116 if ( aRequestedAttributes.getLength() == 0 )
2117 {
2118 rDefAttrSeq = aDefAttrSeq;
2119 }
2120 else
2121 {
2122 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
2123 const sal_Int32 nLength = aRequestedAttributes.getLength();
2124 for( sal_Int32 i = 0; i < nLength; ++i )
2125 {
2126 tAccParaPropValMap::const_iterator const aIter = aDefAttrSeq.find( pReqAttrs[i] );
2127 if ( aIter != aDefAttrSeq.end() )
2128 {
2129 rDefAttrSeq[ aIter->first ] = aIter->second;
2130 }
2131 }
2132 }
2133 }
2134
getDefaultAttributes(const uno::Sequence<::rtl::OUString> & aRequestedAttributes)2135 uno::Sequence< PropertyValue > SwAccessibleParagraph::getDefaultAttributes(
2136 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
2137 throw ( uno::RuntimeException )
2138 {
2139 vos::OGuard aGuard(Application::GetSolarMutex());
2140 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2141
2142 tAccParaPropValMap aDefAttrSeq;
2143 _getDefaultAttributesImpl( aRequestedAttributes, aDefAttrSeq );
2144
2145 // --> OD 2010-03-08 #i92233#
2146 static rtl::OUString sMMToPixelRatio( rtl::OUString::createFromAscii( "MMToPixelRatio" ) );
2147 bool bProvideMMToPixelRatio( false );
2148 {
2149 if ( aRequestedAttributes.getLength() == 0 )
2150 {
2151 bProvideMMToPixelRatio = true;
2152 }
2153 else
2154 {
2155 const rtl::OUString* aRequestedAttrIter =
2156 ::std::find( ::comphelper::stl_begin( aRequestedAttributes ),
2157 ::comphelper::stl_end( aRequestedAttributes ),
2158 sMMToPixelRatio );
2159 if ( aRequestedAttrIter != ::comphelper::stl_end( aRequestedAttributes ) )
2160 {
2161 bProvideMMToPixelRatio = true;
2162 }
2163 }
2164 }
2165 // <--
2166
2167 uno::Sequence< PropertyValue > aValues( aDefAttrSeq.size() +
2168 ( bProvideMMToPixelRatio ? 1 : 0 ) );
2169 PropertyValue* pValues = aValues.getArray();
2170 sal_Int32 i = 0;
2171 for ( tAccParaPropValMap::const_iterator aIter = aDefAttrSeq.begin();
2172 aIter != aDefAttrSeq.end();
2173 ++aIter )
2174 {
2175 pValues[i] = aIter->second;
2176 ++i;
2177 }
2178
2179 // --> OD 2010-03-08 #i92233#
2180 if ( bProvideMMToPixelRatio )
2181 {
2182 PropertyValue rPropVal;
2183 rPropVal.Name = sMMToPixelRatio;
2184 const Size a100thMMSize( 1000, 1000 );
2185 const Size aPixelSize = GetMap()->LogicToPixel( a100thMMSize );
2186 const float fRatio = ((float)a100thMMSize.Width()/100)/aPixelSize.Width();
2187 rPropVal.Value = uno::makeAny( fRatio );
2188 rPropVal.Handle = -1;
2189 rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
2190 pValues[ aValues.getLength() - 1 ] = rPropVal;
2191 }
2192 // <--
2193
2194 return aValues;
2195 }
2196
_getRunAttributesImpl(const sal_Int32 nIndex,const uno::Sequence<::rtl::OUString> & aRequestedAttributes,tAccParaPropValMap & rRunAttrSeq)2197 void SwAccessibleParagraph::_getRunAttributesImpl(
2198 const sal_Int32 nIndex,
2199 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
2200 tAccParaPropValMap& rRunAttrSeq )
2201 {
2202 // create PaM for character at position <nIndex>
2203 SwPaM* pPaM( 0 );
2204 {
2205 const SwTxtNode* pTxtNode( GetTxtNode() );
2206 SwPosition* pStartPos = new SwPosition( *pTxtNode );
2207 pStartPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex) );
2208 SwPosition* pEndPos = new SwPosition( *pTxtNode );
2209 pEndPos->nContent.Assign( const_cast<SwTxtNode*>(pTxtNode), static_cast<sal_uInt16>(nIndex+1) );
2210
2211 pPaM = new SwPaM( *pStartPos, *pEndPos );
2212
2213 delete pStartPos;
2214 delete pEndPos;
2215 }
2216
2217 // retrieve character attributes for the created PaM <pPaM>
2218 SfxItemSet aSet( pPaM->GetDoc()->GetAttrPool(),
2219 RES_CHRATR_BEGIN, RES_CHRATR_END -1,
2220 0 );
2221 // --> OD 2007-11-12 #i82637#
2222 // From the perspective of the a11y API the character attributes, which
2223 // are set at the automatic paragraph style of the paragraph are treated
2224 // as run attributes.
2225 // SwXTextCursor::GetCrsrAttr( *pPaM, aSet, sal_True, sal_True );
2226 // get character attributes from automatic paragraph style and merge these into <aSet>
2227 {
2228 const SwTxtNode* pTxtNode( GetTxtNode() );
2229 if ( pTxtNode->HasSwAttrSet() )
2230 {
2231 SfxItemSet aAutomaticParaStyleCharAttrs( pPaM->GetDoc()->GetAttrPool(),
2232 RES_CHRATR_BEGIN, RES_CHRATR_END -1,
2233 0 );
2234 aAutomaticParaStyleCharAttrs.Put( *(pTxtNode->GetpSwAttrSet()), sal_False );
2235 aSet.Put( aAutomaticParaStyleCharAttrs );
2236 }
2237 }
2238 // get character attributes at <pPaM> and merge these into <aSet>
2239 {
2240 SfxItemSet aCharAttrsAtPaM( pPaM->GetDoc()->GetAttrPool(),
2241 RES_CHRATR_BEGIN, RES_CHRATR_END -1,
2242 0 );
2243 SwUnoCursorHelper::GetCrsrAttr(*pPaM, aCharAttrsAtPaM, sal_True, sal_True);
2244 aSet.Put( aCharAttrsAtPaM );
2245 }
2246 // <--
2247
2248 // build-up sequence containing the run attributes <rRunAttrSeq>
2249 {
2250 tAccParaPropValMap aRunAttrSeq;
2251 {
2252 // --> OD 2007-11-12 #i82637#
2253 tAccParaPropValMap aDefAttrSeq;
2254 uno::Sequence< ::rtl::OUString > aDummy;
2255 _getDefaultAttributesImpl( aDummy, aDefAttrSeq, true );
2256 // <--
2257
2258 const SfxItemPropertyMap* pPropMap =
2259 aSwMapProvider.GetPropertySet( PROPERTY_MAP_TEXT_CURSOR )->getPropertyMap();
2260 PropertyEntryVector_t aPropertyEntries = pPropMap->getPropertyEntries();
2261 PropertyEntryVector_t::const_iterator aPropIt = aPropertyEntries.begin();
2262 while ( aPropIt != aPropertyEntries.end() )
2263 {
2264 const SfxPoolItem* pItem( 0 );
2265 // --> OD 2007-11-12 #i82637#
2266 // Found character attributes, whose value equals the value of
2267 // the corresponding default character attributes, are excluded.
2268 if ( aSet.GetItemState( aPropIt->nWID, sal_True, &pItem ) == SFX_ITEM_SET )
2269 {
2270 uno::Any aVal;
2271 pItem->QueryValue( aVal, aPropIt->nMemberId );
2272
2273 PropertyValue rPropVal;
2274 rPropVal.Name = aPropIt->sName;
2275 rPropVal.Value = aVal;
2276 rPropVal.Handle = -1;
2277 rPropVal.State = PropertyState_DIRECT_VALUE;
2278
2279 tAccParaPropValMap::const_iterator aDefIter =
2280 aDefAttrSeq.find( rPropVal.Name );
2281 if ( aDefIter == aDefAttrSeq.end() ||
2282 rPropVal.Value != aDefIter->second.Value )
2283 {
2284 aRunAttrSeq[rPropVal.Name] = rPropVal;
2285 }
2286 }
2287
2288 ++aPropIt;
2289 }
2290 }
2291
2292 if ( aRequestedAttributes.getLength() == 0 )
2293 {
2294 rRunAttrSeq = aRunAttrSeq;
2295 }
2296 else
2297 {
2298 const ::rtl::OUString* pReqAttrs = aRequestedAttributes.getConstArray();
2299 const sal_Int32 nLength = aRequestedAttributes.getLength();
2300 for( sal_Int32 i = 0; i < nLength; ++i )
2301 {
2302 tAccParaPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
2303 if ( aIter != aRunAttrSeq.end() )
2304 {
2305 rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
2306 }
2307 }
2308 }
2309 }
2310
2311 delete pPaM;
2312 }
2313
getRunAttributes(sal_Int32 nIndex,const uno::Sequence<::rtl::OUString> & aRequestedAttributes)2314 uno::Sequence< PropertyValue > SwAccessibleParagraph::getRunAttributes(
2315 sal_Int32 nIndex,
2316 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes )
2317 throw ( lang::IndexOutOfBoundsException,
2318 uno::RuntimeException )
2319 {
2320 vos::OGuard aGuard(Application::GetSolarMutex());
2321 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2322
2323 {
2324 const ::rtl::OUString& rText = GetString();
2325 if ( !IsValidChar( nIndex, rText.getLength() ) )
2326 {
2327 throw lang::IndexOutOfBoundsException();
2328 }
2329 }
2330
2331 tAccParaPropValMap aRunAttrSeq;
2332 _getRunAttributesImpl( nIndex, aRequestedAttributes, aRunAttrSeq );
2333
2334 uno::Sequence< PropertyValue > aValues( aRunAttrSeq.size() );
2335 PropertyValue* pValues = aValues.getArray();
2336 sal_Int32 i = 0;
2337 for ( tAccParaPropValMap::const_iterator aIter = aRunAttrSeq.begin();
2338 aIter != aRunAttrSeq.end();
2339 ++aIter )
2340 {
2341 pValues[i] = aIter->second;
2342 ++i;
2343 }
2344
2345 return aValues;
2346 }
2347 // <--
_getSupplementalAttributesImpl(const sal_Int32,const uno::Sequence<::rtl::OUString> & aRequestedAttributes,tAccParaPropValMap & rSupplementalAttrSeq)2348 void SwAccessibleParagraph::_getSupplementalAttributesImpl(
2349 const sal_Int32,
2350 const uno::Sequence< ::rtl::OUString >& aRequestedAttributes,
2351 tAccParaPropValMap& rSupplementalAttrSeq )
2352 {
2353 const SwTxtNode* pTxtNode( GetTxtNode() );
2354 ::boost::scoped_ptr<SfxItemSet> pSet;
2355 pSet.reset( new SfxItemSet( const_cast<SwAttrPool&>(pTxtNode->GetDoc()->GetAttrPool()),
2356 RES_PARATR_ADJUST, RES_PARATR_ADJUST,
2357 RES_PARATR_TABSTOP, RES_PARATR_TABSTOP,
2358 RES_PARATR_LINESPACING, RES_PARATR_LINESPACING,
2359 RES_UL_SPACE, RES_UL_SPACE,
2360 RES_LR_SPACE, RES_LR_SPACE,
2361 RES_PARATR_NUMRULE, RES_PARATR_NUMRULE,
2362 RES_PARATR_LIST_BEGIN, RES_PARATR_LIST_END-1,
2363 0 ) );
2364
2365 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() )
2366 {
2367 pSet->Put( pTxtNode->GetAttr(RES_PARATR_LIST_LEVEL, RES_PARATR_LIST_LEVEL) );
2368 }
2369 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_UL_SPACE) );
2370 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_LR_SPACE) );
2371 pSet->Put( pTxtNode->SwCntntNode::GetAttr(RES_PARATR_ADJUST) );
2372
2373 tAccParaPropValMap aSupplementalAttrSeq;
2374 {
2375 const SfxItemPropertyMapEntry* pPropMap(
2376 aSwMapProvider.GetPropertyMapEntries( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ) );
2377 while ( pPropMap->pName )
2378 {
2379 const SfxPoolItem* pItem = pSet->GetItem( pPropMap->nWID );
2380 if ( pItem )
2381 {
2382 uno::Any aVal;
2383 pItem->QueryValue( aVal, pPropMap->nMemberId );
2384
2385 PropertyValue rPropVal;
2386 rPropVal.Name = OUString::createFromAscii( pPropMap->pName );
2387 rPropVal.Value = aVal;
2388 rPropVal.Handle = -1;
2389 rPropVal.State = beans::PropertyState_DEFAULT_VALUE;
2390
2391 aSupplementalAttrSeq[rPropVal.Name] = rPropVal;
2392 }
2393
2394 ++pPropMap;
2395 }
2396 }
2397
2398 const OUString* pSupplementalAttrs = aRequestedAttributes.getConstArray();
2399 const sal_Int32 nSupplementalLength = aRequestedAttributes.getLength();
2400
2401 for( sal_Int32 index = 0; index < nSupplementalLength; ++index )
2402 {
2403 tAccParaPropValMap::const_iterator const aIter = aSupplementalAttrSeq.find( pSupplementalAttrs[index] );
2404 if ( aIter != aSupplementalAttrSeq.end() )
2405 {
2406 rSupplementalAttrSeq[ aIter->first ] = aIter->second;
2407 }
2408 }
2409 }
2410
_correctValues(const sal_Int32 nIndex,uno::Sequence<PropertyValue> & rValues)2411 void SwAccessibleParagraph::_correctValues( const sal_Int32 nIndex,
2412 uno::Sequence< PropertyValue >& rValues)
2413 {
2414 PropertyValue ChangeAttr, ChangeAttrColor;
2415
2416 const SwRedline* pRedline = GetRedlineAtIndex( nIndex );
2417 if ( pRedline )
2418 {
2419
2420 const SwModuleOptions *pOpt = SW_MOD()->GetModuleConfig();
2421 AuthorCharAttr aChangeAttr;
2422 if ( pOpt )
2423 {
2424 switch( pRedline->GetType())
2425 {
2426 case nsRedlineType_t::REDLINE_INSERT:
2427 aChangeAttr = pOpt->GetInsertAuthorAttr();
2428 break;
2429 case nsRedlineType_t::REDLINE_DELETE:
2430 aChangeAttr = pOpt->GetDeletedAuthorAttr();
2431 break;
2432 case nsRedlineType_t::REDLINE_FORMAT:
2433 aChangeAttr = pOpt->GetFormatAuthorAttr();
2434 break;
2435 }
2436 }
2437 switch( aChangeAttr.nItemId )
2438 {
2439 case SID_ATTR_CHAR_WEIGHT:
2440 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_WEIGHT).pName );
2441 ChangeAttr.Value <<= awt::FontWeight::BOLD;
2442 break;
2443 case SID_ATTR_CHAR_POSTURE:
2444 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_POSTURE).pName );
2445 ChangeAttr.Value <<= awt::FontSlant_ITALIC; //char posture
2446 break;
2447 case SID_ATTR_CHAR_STRIKEOUT:
2448 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_STRIKEOUT).pName );
2449 ChangeAttr.Value <<= awt::FontStrikeout::SINGLE; //char strikeout
2450 break;
2451 case SID_ATTR_CHAR_UNDERLINE:
2452 ChangeAttr.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE).pName );
2453 ChangeAttr.Value <<= aChangeAttr.nAttr; //underline line
2454 break;
2455 }
2456 if( aChangeAttr.nColor != COL_NONE )
2457 {
2458 if( aChangeAttr.nItemId == SID_ATTR_BRUSH )
2459 {
2460 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR).pName );
2461 if( aChangeAttr.nColor == COL_TRANSPARENT )//char backcolor
2462 ChangeAttrColor.Value <<= COL_BLUE;
2463 else
2464 ChangeAttrColor.Value <<= aChangeAttr.nColor;
2465 }
2466 else
2467 {
2468 ChangeAttrColor.Name = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName );
2469 if( aChangeAttr.nColor == COL_TRANSPARENT )//char color
2470 ChangeAttrColor.Value <<= COL_BLUE;
2471 else
2472 ChangeAttrColor.Value <<= aChangeAttr.nColor;
2473 }
2474 }
2475 }
2476
2477 PropertyValue* pValues = rValues.getArray();
2478
2479 const SwTxtNode* pTxtNode( GetTxtNode() );
2480
2481 sal_Int32 nValues = rValues.getLength();
2482 for (sal_Int32 i = 0; i < nValues; ++i)
2483 {
2484 PropertyValue& rValue = pValues[i];
2485
2486 if (rValue.Name.compareTo( ChangeAttr.Name )==0)
2487 {
2488 rValue.Value = ChangeAttr.Value;
2489 continue;
2490 }
2491
2492 if (rValue.Name.compareTo( ChangeAttrColor.Name )==0)
2493 {
2494 rValue.Value = ChangeAttr.Value;
2495 continue;
2496 }
2497
2498 //back color
2499 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_BACK_COLOR ).pName ) )==0)
2500 {
2501 uno::Any &anyChar = rValue.Value;
2502 sal_uInt32 crBack = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2503 if (COL_AUTO == crBack)
2504 {
2505 uno::Reference<XAccessibleComponent> xComponent(this);
2506 if (xComponent.is())
2507 {
2508 crBack = (sal_uInt32)xComponent->getBackground();
2509 }
2510 rValue.Value <<= crBack;
2511 }
2512 continue;
2513 }
2514
2515 //char color
2516 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_COLOR ).pName ) )==0)
2517 {
2518 if( GetPortionData().IsInGrayPortion( nIndex ) )
2519 rValue.Value <<= SwViewOption::GetFieldShadingsColor().GetColor();
2520 uno::Any &anyChar = rValue.Value;
2521 sal_uInt32 crChar = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2522
2523 if( COL_AUTO == crChar )
2524 {
2525 uno::Reference<XAccessibleComponent> xComponent(this);
2526 if (xComponent.is())
2527 {
2528 Color cr(xComponent->getBackground());
2529 crChar = cr.IsDark() ? COL_WHITE : COL_BLACK;
2530 rValue.Value <<= crChar;
2531 }
2532 }
2533 continue;
2534 }
2535
2536 // UnderLine
2537 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE ).pName ) )==0)
2538 {
2539 //misspelled word
2540 SwCrsrShell* pCrsrShell = GetCrsrShell();
2541 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell())
2542 {
2543 const SwWrongList* pWrongList = pTxtNode->GetWrong();
2544 if( NULL != pWrongList )
2545 {
2546 xub_StrLen nBegin = nIndex;
2547 xub_StrLen nLen = 1;
2548 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) )
2549 {
2550 rValue.Value <<= (sal_uInt16)UNDERLINE_WAVE;
2551 }
2552 }
2553 }
2554 continue;
2555 }
2556
2557 // UnderLineColor
2558 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_UNDERLINE_COLOR ).pName ) )==0)
2559 {
2560 //misspelled word
2561 SwCrsrShell* pCrsrShell = GetCrsrShell();
2562 if( pCrsrShell != NULL && pCrsrShell->GetViewOptions() && pCrsrShell->GetViewOptions()->IsOnlineSpell())
2563 {
2564 const SwWrongList* pWrongList = pTxtNode->GetWrong();
2565 if( NULL != pWrongList )
2566 {
2567 xub_StrLen nBegin = nIndex;
2568 xub_StrLen nLen = 1;
2569 if( pWrongList->InWrongWord(nBegin,nLen) && !pTxtNode->IsSymbol(nBegin) )
2570 {
2571 rValue.Value <<= (sal_Int32)0x00ff0000;
2572 continue;
2573 }
2574 }
2575 }
2576
2577 uno::Any &anyChar = rValue.Value;
2578 sal_uInt32 crUnderline = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
2579 if ( COL_AUTO == crUnderline )
2580 {
2581 uno::Reference<XAccessibleComponent> xComponent(this);
2582 if (xComponent.is())
2583 {
2584 Color cr(xComponent->getBackground());
2585 crUnderline = cr.IsDark() ? COL_WHITE : COL_BLACK;
2586 rValue.Value <<= crUnderline;
2587 }
2588 }
2589
2590 continue;
2591 }
2592
2593 //tab stop
2594 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_TABSTOPS ).pName ) )==0)
2595 {
2596 com::sun::star::uno::Sequence< ::com::sun::star::style::TabStop > tabs = GetCurrentTabStop( nIndex );
2597 if( !tabs.hasElements() )
2598 {
2599 tabs.realloc(1);
2600 ::com::sun::star::style::TabStop ts;
2601 com::sun::star::awt::Rectangle rc0 = getCharacterBounds(0);
2602 com::sun::star::awt::Rectangle rc1 = getCharacterBounds(nIndex);
2603 if( rc1.X - rc0.X >= 48 )
2604 ts.Position = (rc1.X - rc0.X) - (rc1.X - rc0.X - 48)% 47 + 47;
2605 else
2606 ts.Position = 48;
2607 ts.DecimalChar = ' ';
2608 ts.FillChar = ' ';
2609 ts.Alignment = ::com::sun::star::style::TabAlign_LEFT;
2610 tabs[0] = ts;
2611 }
2612 rValue.Value <<= tabs;
2613 continue;
2614 }
2615
2616 //number bullet
2617 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_NUMBERING_RULES ).pName ) )==0)
2618 {
2619 if ( pTxtNode->HasBullet() || pTxtNode->HasNumber() )
2620 {
2621 uno::Any aVal;
2622 SwNumRule* pNumRule = pTxtNode->GetNumRule();
2623 if (pNumRule)
2624 {
2625 uno::Reference< container::XIndexReplace > xNum = new SwXNumberingRules(*pNumRule);
2626 aVal.setValue(&xNum, ::getCppuType((const uno::Reference< container::XIndexReplace >*)0));
2627 }
2628 rValue.Value <<= aVal;
2629 }
2630 continue;
2631 }
2632
2633 //footnote & endnote
2634 if (rValue.Name.compareTo(::rtl::OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName ) )==0)
2635 {
2636 if ( GetPortionData().IsIndexInFootnode(nIndex) )
2637 {
2638 const OUString sEscapmentName = OUString::createFromAscii( GetPropName( UNO_NAME_CHAR_ESCAPEMENT ).pName );
2639 rValue.Value <<= (sal_Int32)101;
2640 }
2641 continue;
2642 }
2643 }
2644 }
2645
getCharacterBounds(sal_Int32 nIndex)2646 awt::Rectangle SwAccessibleParagraph::getCharacterBounds(
2647 sal_Int32 nIndex )
2648 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2649 {
2650 vos::OGuard aGuard(Application::GetSolarMutex());
2651
2652 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2653
2654
2655 /* #i12332# The position after the string needs special treatment.
2656 IsValidChar -> IsValidPosition
2657 */
2658 if( ! (IsValidPosition( nIndex, GetString().getLength() ) ) )
2659 throw lang::IndexOutOfBoundsException();
2660
2661 /* #i12332# */
2662 sal_Bool bBehindText = sal_False;
2663 if ( nIndex == GetString().getLength() )
2664 bBehindText = sal_True;
2665
2666 // get model position & prepare GetCharRect() arguments
2667 SwCrsrMoveState aMoveState;
2668 aMoveState.bRealHeight = sal_True;
2669 aMoveState.bRealWidth = sal_True;
2670 SwSpecialPos aSpecialPos;
2671 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
2672
2673 sal_uInt16 nPos = 0;
2674
2675 /* #i12332# FillSpecialPos does not accept nIndex ==
2676 GetString().getLength(). In that case nPos is set to the
2677 length of the string in the core. This way GetCharRect
2678 returns the rectangle for a cursor at the end of the
2679 paragraph. */
2680 if (bBehindText)
2681 {
2682 nPos = pNode->GetTxt().Len();
2683 }
2684 else
2685 nPos = GetPortionData().FillSpecialPos
2686 (nIndex, aSpecialPos, aMoveState.pSpecialPos );
2687
2688 // call GetCharRect
2689 SwRect aCoreRect;
2690 SwIndex aIndex( pNode, nPos );
2691 SwPosition aPosition( *pNode, aIndex );
2692 GetFrm()->GetCharRect( aCoreRect, aPosition, &aMoveState );
2693
2694 // translate core coordinates into accessibility coordinates
2695 Window *pWin = GetWindow();
2696 CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
2697
2698 Rectangle aScreenRect( GetMap()->CoreToPixel( aCoreRect.SVRect() ));
2699 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
2700
2701 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
2702 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
2703
2704 // convert into AWT Rectangle
2705 return awt::Rectangle(
2706 aScreenRect.Left(), aScreenRect.Top(),
2707 aScreenRect.GetWidth(), aScreenRect.GetHeight() );
2708 }
2709
getCharacterCount()2710 sal_Int32 SwAccessibleParagraph::getCharacterCount()
2711 throw (uno::RuntimeException)
2712 {
2713 vos::OGuard aGuard(Application::GetSolarMutex());
2714
2715 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2716
2717 return GetString().getLength();
2718 }
2719
getIndexAtPoint(const awt::Point & rPoint)2720 sal_Int32 SwAccessibleParagraph::getIndexAtPoint( const awt::Point& rPoint )
2721 throw (uno::RuntimeException)
2722 {
2723 vos::OGuard aGuard(Application::GetSolarMutex());
2724
2725
2726 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2727
2728 // construct SwPosition (where GetCrsrOfst() will put the result into)
2729 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
2730 SwIndex aIndex( pNode, 0);
2731 SwPosition aPos( *pNode, aIndex );
2732
2733 // construct Point (translate into layout coordinates)
2734 Window *pWin = GetWindow();
2735 CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
2736 Point aPoint( rPoint.X, rPoint.Y );
2737 SwRect aLogBounds( GetBounds( *(GetMap()), GetFrm() ) ); // twip rel to doc root
2738 Point aPixPos( GetMap()->CoreToPixel( aLogBounds.SVRect() ).TopLeft() );
2739 aPoint.X() += aPixPos.X();
2740 aPoint.Y() += aPixPos.Y();
2741 MapMode aMapMode = pWin->GetMapMode();
2742 Point aCorePoint( GetMap()->PixelToCore( aPoint ) );
2743 if( !aLogBounds.IsInside( aCorePoint ) )
2744 {
2745 /* #i12332# rPoint is may also be in rectangle returned by
2746 getCharacterBounds(getCharacterCount() */
2747
2748 awt::Rectangle aRectEndPos =
2749 getCharacterBounds(getCharacterCount());
2750
2751 if (rPoint.X - aRectEndPos.X >= 0 &&
2752 rPoint.X - aRectEndPos.X < aRectEndPos.Width &&
2753 rPoint.Y - aRectEndPos.Y >= 0 &&
2754 rPoint.Y - aRectEndPos.Y < aRectEndPos.Height)
2755 return getCharacterCount();
2756
2757 return -1;
2758 }
2759
2760 // ask core for position
2761 DBG_ASSERT( GetFrm() != NULL, "The text frame has vanished!" );
2762 DBG_ASSERT( GetFrm()->IsTxtFrm(), "The text frame has mutated!" );
2763 const SwTxtFrm* pFrm = static_cast<const SwTxtFrm*>( GetFrm() );
2764 SwCrsrMoveState aMoveState;
2765 aMoveState.bPosMatchesBounds = sal_True;
2766 sal_Bool bSuccess = pFrm->GetCrsrOfst( &aPos, aCorePoint, &aMoveState );
2767
2768 SwIndex aCntntIdx = aPos.nContent;
2769 const xub_StrLen nIndex = aCntntIdx.GetIndex();
2770 if ( nIndex > 0 )
2771 {
2772 SwRect aResultRect;
2773 pFrm->GetCharRect( aResultRect, aPos );
2774 bool bVert = pFrm->IsVertical();
2775 bool bR2L = pFrm->IsRightToLeft();
2776
2777 if ( (!bVert && aResultRect.Pos().X() > aCorePoint.X()) ||
2778 ( bVert && aResultRect.Pos().Y() > aCorePoint.Y()) ||
2779 ( bR2L && aResultRect.Right() < aCorePoint.X()) )
2780 {
2781 SwIndex aIdxPrev( pNode, nIndex - 1);
2782 SwPosition aPosPrev( *pNode, aIdxPrev );
2783 SwRect aResultRectPrev;
2784 pFrm->GetCharRect( aResultRectPrev, aPosPrev );
2785 if ( (!bVert && aResultRectPrev.Pos().X() < aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) ||
2786 ( bVert && aResultRectPrev.Pos().Y() < aCorePoint.Y() && aResultRect.Pos().X() == aResultRectPrev.Pos().X()) ||
2787 ( bR2L && aResultRectPrev.Right() > aCorePoint.X() && aResultRect.Pos().Y() == aResultRectPrev.Pos().Y()) )
2788 aPos = aPosPrev;
2789 }
2790 }
2791
2792 return bSuccess ?
2793 GetPortionData().GetAccessiblePosition( aPos.nContent.GetIndex() )
2794 : -1L;
2795 }
2796
getSelectedText()2797 ::rtl::OUString SwAccessibleParagraph::getSelectedText()
2798 throw (uno::RuntimeException)
2799 {
2800 vos::OGuard aGuard(Application::GetSolarMutex());
2801
2802 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2803
2804 sal_Int32 nStart, nEnd;
2805 sal_Bool bSelected = GetSelection( nStart, nEnd );
2806 return bSelected
2807 ? GetString().copy( nStart, nEnd - nStart )
2808 : ::rtl::OUString();
2809 }
2810
getSelectionStart()2811 sal_Int32 SwAccessibleParagraph::getSelectionStart()
2812 throw (uno::RuntimeException)
2813 {
2814 vos::OGuard aGuard(Application::GetSolarMutex());
2815
2816 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2817
2818 sal_Int32 nStart, nEnd;
2819 GetSelection( nStart, nEnd );
2820 return nStart;
2821 }
2822
getSelectionEnd()2823 sal_Int32 SwAccessibleParagraph::getSelectionEnd()
2824 throw (uno::RuntimeException)
2825 {
2826 vos::OGuard aGuard(Application::GetSolarMutex());
2827
2828 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2829
2830 sal_Int32 nStart, nEnd;
2831 GetSelection( nStart, nEnd );
2832 return nEnd;
2833 }
2834
setSelection(sal_Int32 nStartIndex,sal_Int32 nEndIndex)2835 sal_Bool SwAccessibleParagraph::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2836 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2837 {
2838 vos::OGuard aGuard(Application::GetSolarMutex());
2839
2840 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2841
2842 // parameter checking
2843 sal_Int32 nLength = GetString().getLength();
2844 if ( ! IsValidRange( nStartIndex, nEndIndex, nLength ) )
2845 {
2846 throw lang::IndexOutOfBoundsException();
2847 }
2848
2849 sal_Bool bRet = sal_False;
2850
2851 // get cursor shell
2852 SwCrsrShell* pCrsrShell = GetCrsrShell();
2853 if( pCrsrShell != NULL )
2854 {
2855 // create pam for selection
2856 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
2857 SwIndex aIndex( pNode, GetPortionData().GetModelPosition(nStartIndex));
2858 SwPosition aStartPos( *pNode, aIndex );
2859 SwPaM aPaM( aStartPos );
2860 aPaM.SetMark();
2861 aPaM.GetPoint()->nContent =
2862 GetPortionData().GetModelPosition(nEndIndex);
2863
2864 // set PaM at cursor shell
2865 bRet = Select( aPaM );
2866 }
2867
2868 return bRet;
2869 }
2870
getText()2871 ::rtl::OUString SwAccessibleParagraph::getText()
2872 throw (uno::RuntimeException)
2873 {
2874 vos::OGuard aGuard(Application::GetSolarMutex());
2875
2876 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2877
2878 return GetString();
2879 }
2880
getTextRange(sal_Int32 nStartIndex,sal_Int32 nEndIndex)2881 ::rtl::OUString SwAccessibleParagraph::getTextRange(
2882 sal_Int32 nStartIndex, sal_Int32 nEndIndex )
2883 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
2884 {
2885 vos::OGuard aGuard(Application::GetSolarMutex());
2886
2887 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2888
2889 ::rtl::OUString sText( GetString() );
2890
2891 if ( IsValidRange( nStartIndex, nEndIndex, sText.getLength() ) )
2892 {
2893 OrderRange( nStartIndex, nEndIndex );
2894 return sText.copy(nStartIndex, nEndIndex-nStartIndex );
2895 }
2896 else
2897 throw lang::IndexOutOfBoundsException();
2898 }
2899
getTextAtIndex(sal_Int32 nIndex,sal_Int16 nTextType)2900 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextAtIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
2901 {
2902 vos::OGuard aGuard(Application::GetSolarMutex());
2903
2904 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2905
2906 /*accessibility::*/TextSegment aResult;
2907 aResult.SegmentStart = -1;
2908 aResult.SegmentEnd = -1;
2909
2910 const ::rtl::OUString rText = GetString();
2911 // implement the silly specification that first position after
2912 // text must return an empty string, rather than throwing an
2913 // IndexOutOfBoundsException, except for LINE, where the last
2914 // line is returned
2915 if( nIndex == rText.getLength() && AccessibleTextType::LINE != nTextType )
2916 return aResult;
2917
2918 // with error checking
2919 i18n::Boundary aBound;
2920 sal_Bool bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2921
2922 DBG_ASSERT( aBound.startPos >= 0, "illegal boundary" );
2923 DBG_ASSERT( aBound.startPos <= aBound.endPos, "illegal boundary" );
2924
2925 // return word (if present)
2926 if ( bWord )
2927 {
2928 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
2929 aResult.SegmentStart = aBound.startPos;
2930 aResult.SegmentEnd = aBound.endPos;
2931 }
2932
2933 return aResult;
2934 }
2935
getTextBeforeIndex(sal_Int32 nIndex,sal_Int16 nTextType)2936 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
2937 {
2938 vos::OGuard aGuard(Application::GetSolarMutex());
2939
2940 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
2941
2942 const ::rtl::OUString rText = GetString();
2943
2944 /*accessibility::*/TextSegment aResult;
2945 aResult.SegmentStart = -1;
2946 aResult.SegmentEnd = -1;
2947 //If nIndex = 0, then nobefore text so return -1 directly.
2948 if( nIndex == 0 )
2949 return aResult;
2950 //Tab will be return when call WORDTYPE
2951
2952 // get starting pos
2953 i18n::Boundary aBound;
2954 if (nIndex == rText.getLength())
2955 aBound.startPos = aBound.endPos = nIndex;
2956 else
2957 {
2958 sal_Bool bTmp = GetTextBoundary( aBound, rText, nIndex, nTextType );
2959
2960 if ( ! bTmp )
2961 aBound.startPos = aBound.endPos = nIndex;
2962 }
2963
2964 // now skip to previous word
2965 if (nTextType==2 || nTextType == 3)
2966 {
2967 i18n::Boundary preBound = aBound;
2968 while(preBound.startPos==aBound.startPos && nIndex > 0)
2969 {
2970 nIndex = min( nIndex, preBound.startPos ) - 1;
2971 if( nIndex < 0 ) break;
2972 GetTextBoundary( preBound, rText, nIndex, nTextType );
2973 }
2974 //if (nIndex>0)
2975 if (nIndex>=0)
2976 //Tab will be return when call WORDTYPE
2977 {
2978 aResult.SegmentText = rText.copy( preBound.startPos, preBound.endPos - preBound.startPos );
2979 aResult.SegmentStart = preBound.startPos;
2980 aResult.SegmentEnd = preBound.endPos;
2981 }
2982 }
2983 else
2984 {
2985 sal_Bool bWord = sal_False;
2986 while( !bWord )
2987 {
2988 nIndex = min( nIndex, aBound.startPos ) - 1;
2989 if( nIndex >= 0 )
2990 {
2991 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
2992 }
2993 else
2994 break; // exit if beginning of string is reached
2995 }
2996
2997 if (bWord && nIndex<rText.getLength())
2998 {
2999 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
3000 aResult.SegmentStart = aBound.startPos;
3001 aResult.SegmentEnd = aBound.endPos;
3002 }
3003 }
3004 return aResult;
3005 }
3006
getTextBehindIndex(sal_Int32 nIndex,sal_Int16 nTextType)3007 /*accessibility::*/TextSegment SwAccessibleParagraph::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 nTextType ) throw (lang::IndexOutOfBoundsException, lang::IllegalArgumentException, uno::RuntimeException)
3008 {
3009 vos::OGuard aGuard(Application::GetSolarMutex());
3010
3011 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3012
3013 /*accessibility::*/TextSegment aResult;
3014 aResult.SegmentStart = -1;
3015 aResult.SegmentEnd = -1;
3016 const ::rtl::OUString rText = GetString();
3017
3018 // implement the silly specification that first position after
3019 // text must return an empty string, rather than throwing an
3020 // IndexOutOfBoundsException
3021 if( nIndex == rText.getLength() )
3022 return aResult;
3023
3024
3025 // get first word, then skip to next word
3026 i18n::Boundary aBound;
3027 GetTextBoundary( aBound, rText, nIndex, nTextType );
3028 sal_Bool bWord = sal_False;
3029 while( !bWord )
3030 {
3031 nIndex = max( sal_Int32(nIndex+1), aBound.endPos );
3032 if( nIndex < rText.getLength() )
3033 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
3034 else
3035 break; // exit if end of string is reached
3036 }
3037
3038 if ( bWord )
3039 {
3040 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
3041 aResult.SegmentStart = aBound.startPos;
3042 aResult.SegmentEnd = aBound.endPos;
3043 }
3044
3045 /*
3046 sal_Bool bWord = sal_False;
3047 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
3048
3049 if (nTextType==2)
3050 {
3051 Boundary nexBound=aBound;
3052
3053 // real current word
3054 if( nIndex <= aBound.endPos && nIndex >= aBound.startPos )
3055 {
3056 while(nexBound.endPos==aBound.endPos&&nIndex<rText.getLength())
3057 {
3058 // nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) + 1;
3059 nIndex = max( (sal_Int32)(nIndex), nexBound.endPos) ;
3060 const sal_Unicode* pStr = rText.getStr();
3061 if (pStr)
3062 {
3063 if( pStr[nIndex] == sal_Unicode(' ') )
3064 nIndex++;
3065 }
3066 if( nIndex < rText.getLength() )
3067 {
3068 bWord = GetTextBoundary( nexBound, rText, nIndex, nTextType );
3069 }
3070 }
3071 }
3072
3073 if (bWord && nIndex<rText.getLength())
3074 {
3075 aResult.SegmentText = rText.copy( nexBound.startPos, nexBound.endPos - nexBound.startPos );
3076 aResult.SegmentStart = nexBound.startPos;
3077 aResult.SegmentEnd = nexBound.endPos;
3078 }
3079
3080 }
3081 else
3082 {
3083 bWord = sal_False;
3084 while( !bWord )
3085 {
3086 nIndex = max( (sal_Int32)(nIndex+1), aBound.endPos );
3087 if( nIndex < rText.getLength() )
3088 {
3089 bWord = GetTextBoundary( aBound, rText, nIndex, nTextType );
3090 }
3091 else
3092 break; // exit if end of string is reached
3093 }
3094 if (bWord && nIndex<rText.getLength())
3095 {
3096 aResult.SegmentText = rText.copy( aBound.startPos, aBound.endPos - aBound.startPos );
3097 aResult.SegmentStart = aBound.startPos;
3098 aResult.SegmentEnd = aBound.endPos;
3099 }
3100 }
3101 */
3102 return aResult;
3103 }
3104
copyText(sal_Int32 nStartIndex,sal_Int32 nEndIndex)3105 sal_Bool SwAccessibleParagraph::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
3106 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3107 {
3108 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3109 vos::OGuard aGuard(Application::GetSolarMutex());
3110
3111 // select and copy (through dispatch mechanism)
3112 setSelection( nStartIndex, nEndIndex );
3113 ExecuteAtViewShell( SID_COPY );
3114 return sal_True;
3115 }
3116
3117
3118 //
3119 //===== XAccesibleEditableText ==========================================
3120 //
3121
cutText(sal_Int32 nStartIndex,sal_Int32 nEndIndex)3122 sal_Bool SwAccessibleParagraph::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
3123 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3124 {
3125 CHECK_FOR_DEFUNC( XAccessibleEditableText );
3126 vos::OGuard aGuard(Application::GetSolarMutex());
3127
3128 if( !IsEditableState() )
3129 return sal_False;
3130
3131 // select and cut (through dispatch mechanism)
3132 setSelection( nStartIndex, nEndIndex );
3133 ExecuteAtViewShell( SID_CUT );
3134 return sal_True;
3135 }
3136
pasteText(sal_Int32 nIndex)3137 sal_Bool SwAccessibleParagraph::pasteText( sal_Int32 nIndex )
3138 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3139 {
3140 CHECK_FOR_DEFUNC( XAccessibleEditableText );
3141 vos::OGuard aGuard(Application::GetSolarMutex());
3142
3143 if( !IsEditableState() )
3144 return sal_False;
3145
3146 // select and paste (through dispatch mechanism)
3147 setSelection( nIndex, nIndex );
3148 ExecuteAtViewShell( SID_PASTE );
3149 return sal_True;
3150 }
3151
deleteText(sal_Int32 nStartIndex,sal_Int32 nEndIndex)3152 sal_Bool SwAccessibleParagraph::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
3153 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3154 {
3155 return replaceText( nStartIndex, nEndIndex, ::rtl::OUString() );
3156 }
3157
insertText(const::rtl::OUString & sText,sal_Int32 nIndex)3158 sal_Bool SwAccessibleParagraph::insertText( const ::rtl::OUString& sText, sal_Int32 nIndex )
3159 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3160 {
3161 return replaceText( nIndex, nIndex, sText );
3162 }
3163
replaceText(sal_Int32 nStartIndex,sal_Int32 nEndIndex,const::rtl::OUString & sReplacement)3164 sal_Bool SwAccessibleParagraph::replaceText(
3165 sal_Int32 nStartIndex, sal_Int32 nEndIndex,
3166 const ::rtl::OUString& sReplacement )
3167 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3168 {
3169 vos::OGuard aGuard(Application::GetSolarMutex());
3170
3171 CHECK_FOR_DEFUNC( XAccessibleEditableText );
3172
3173 const ::rtl::OUString& rText = GetString();
3174
3175 if( IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
3176 {
3177 if( !IsEditableState() )
3178 return sal_False;
3179
3180 SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
3181
3182 // translate positions
3183 sal_uInt16 nStart, nEnd;
3184 sal_Bool bSuccess = GetPortionData().GetEditableRange(
3185 nStartIndex, nEndIndex, nStart, nEnd );
3186
3187 // edit only if the range is editable
3188 if( bSuccess )
3189 {
3190 // create SwPosition for nStartIndex
3191 SwIndex aIndex( pNode, nStart );
3192 SwPosition aStartPos( *pNode, aIndex );
3193
3194 // create SwPosition for nEndIndex
3195 SwPosition aEndPos( aStartPos );
3196 aEndPos.nContent = nEnd;
3197
3198 // now create XTextRange as helper and set string
3199 const uno::Reference<text::XTextRange> xRange(
3200 SwXTextRange::CreateXTextRange(
3201 *pNode->GetDoc(), aStartPos, &aEndPos));
3202 xRange->setString(sReplacement);
3203
3204 // delete portion data
3205 ClearPortionData();
3206 }
3207
3208 return bSuccess;
3209 }
3210 else
3211 throw lang::IndexOutOfBoundsException();
3212 }
3213
3214
setAttributes(sal_Int32 nStartIndex,sal_Int32 nEndIndex,const uno::Sequence<PropertyValue> & rAttributeSet)3215 sal_Bool SwAccessibleParagraph::setAttributes(
3216 sal_Int32 nStartIndex,
3217 sal_Int32 nEndIndex,
3218 const uno::Sequence<PropertyValue>& rAttributeSet )
3219 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3220 {
3221 vos::OGuard aGuard(Application::GetSolarMutex());
3222 CHECK_FOR_DEFUNC( XAccessibleEditableText );
3223
3224 const ::rtl::OUString& rText = GetString();
3225
3226 if( ! IsValidRange( nStartIndex, nEndIndex, rText.getLength() ) )
3227 throw lang::IndexOutOfBoundsException();
3228
3229 if( !IsEditableState() )
3230 return sal_False;
3231
3232
3233 // create a (dummy) text portion for the sole purpose of calling
3234 // setPropertyValue on it
3235 uno::Reference<XMultiPropertySet> xPortion = CreateUnoPortion( nStartIndex,
3236 nEndIndex );
3237
3238 // build sorted index array
3239 sal_Int32 nLength = rAttributeSet.getLength();
3240 const PropertyValue* pPairs = rAttributeSet.getConstArray();
3241 sal_Int32* pIndices = new sal_Int32[nLength];
3242 sal_Int32 i;
3243 for( i = 0; i < nLength; i++ )
3244 pIndices[i] = i;
3245 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
3246
3247 // create sorted sequences according to index array
3248 uno::Sequence< ::rtl::OUString > aNames( nLength );
3249 ::rtl::OUString* pNames = aNames.getArray();
3250 uno::Sequence< uno::Any > aValues( nLength );
3251 uno::Any* pValues = aValues.getArray();
3252 for( i = 0; i < nLength; i++ )
3253 {
3254 const PropertyValue& rVal = pPairs[pIndices[i]];
3255 pNames[i] = rVal.Name;
3256 pValues[i] = rVal.Value;
3257 }
3258 delete[] pIndices;
3259
3260 // now set the values
3261 sal_Bool bRet = sal_True;
3262 try
3263 {
3264 xPortion->setPropertyValues( aNames, aValues );
3265 }
3266 catch( UnknownPropertyException e )
3267 {
3268 // error handling through return code!
3269 bRet = sal_False;
3270 }
3271
3272 return bRet;
3273 }
3274
setText(const::rtl::OUString & sText)3275 sal_Bool SwAccessibleParagraph::setText( const ::rtl::OUString& sText )
3276 throw (uno::RuntimeException)
3277 {
3278 return replaceText(0, GetString().getLength(), sText);
3279 }
3280
3281 //===== XAccessibleSelection ============================================
3282
selectAccessibleChild(sal_Int32 nChildIndex)3283 void SwAccessibleParagraph::selectAccessibleChild(
3284 sal_Int32 nChildIndex )
3285 throw ( lang::IndexOutOfBoundsException,
3286 uno::RuntimeException )
3287 {
3288 CHECK_FOR_DEFUNC( XAccessibleSelection );
3289
3290 aSelectionHelper.selectAccessibleChild(nChildIndex);
3291 }
3292
isAccessibleChildSelected(sal_Int32 nChildIndex)3293 sal_Bool SwAccessibleParagraph::isAccessibleChildSelected(
3294 sal_Int32 nChildIndex )
3295 throw ( lang::IndexOutOfBoundsException,
3296 uno::RuntimeException )
3297 {
3298 CHECK_FOR_DEFUNC( XAccessibleSelection );
3299
3300 return aSelectionHelper.isAccessibleChildSelected(nChildIndex);
3301 }
3302
clearAccessibleSelection()3303 void SwAccessibleParagraph::clearAccessibleSelection( )
3304 throw ( uno::RuntimeException )
3305 {
3306 CHECK_FOR_DEFUNC( XAccessibleSelection );
3307
3308 aSelectionHelper.clearAccessibleSelection();
3309 }
3310
selectAllAccessibleChildren()3311 void SwAccessibleParagraph::selectAllAccessibleChildren( )
3312 throw ( uno::RuntimeException )
3313 {
3314 CHECK_FOR_DEFUNC( XAccessibleSelection );
3315
3316 aSelectionHelper.selectAllAccessibleChildren();
3317 }
3318
getSelectedAccessibleChildCount()3319 sal_Int32 SwAccessibleParagraph::getSelectedAccessibleChildCount( )
3320 throw ( uno::RuntimeException )
3321 {
3322 CHECK_FOR_DEFUNC( XAccessibleSelection );
3323
3324 return aSelectionHelper.getSelectedAccessibleChildCount();
3325 }
3326
getSelectedAccessibleChild(sal_Int32 nSelectedChildIndex)3327 uno::Reference<XAccessible> SwAccessibleParagraph::getSelectedAccessibleChild(
3328 sal_Int32 nSelectedChildIndex )
3329 throw ( lang::IndexOutOfBoundsException,
3330 uno::RuntimeException)
3331 {
3332 CHECK_FOR_DEFUNC( XAccessibleSelection );
3333
3334 return aSelectionHelper.getSelectedAccessibleChild(nSelectedChildIndex);
3335 }
3336
3337 // --> OD 2004-11-16 #111714# - index has to be treated as global child index.
deselectAccessibleChild(sal_Int32 nChildIndex)3338 void SwAccessibleParagraph::deselectAccessibleChild(
3339 sal_Int32 nChildIndex )
3340 throw ( lang::IndexOutOfBoundsException,
3341 uno::RuntimeException )
3342 {
3343 CHECK_FOR_DEFUNC( XAccessibleSelection );
3344
3345 aSelectionHelper.deselectAccessibleChild( nChildIndex );
3346 }
3347
3348 //===== XAccessibleHypertext ============================================
3349
3350 class SwHyperlinkIter_Impl
3351 {
3352 const SwpHints *pHints;
3353 xub_StrLen nStt;
3354 xub_StrLen nEnd;
3355 sal_uInt16 nPos;
3356
3357 public:
3358 SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm );
3359 const SwTxtAttr *next();
getCurrHintPos() const3360 sal_uInt16 getCurrHintPos() const { return nPos-1; }
3361
startIdx() const3362 xub_StrLen startIdx() const { return nStt; }
endIdx() const3363 xub_StrLen endIdx() const { return nEnd; }
3364 };
3365
SwHyperlinkIter_Impl(const SwTxtFrm * pTxtFrm)3366 SwHyperlinkIter_Impl::SwHyperlinkIter_Impl( const SwTxtFrm *pTxtFrm ) :
3367 pHints( pTxtFrm->GetTxtNode()->GetpSwpHints() ),
3368 nStt( pTxtFrm->GetOfst() ),
3369 nPos( 0 )
3370 {
3371 const SwTxtFrm *pFollFrm = pTxtFrm->GetFollow();
3372 nEnd = pFollFrm ? pFollFrm->GetOfst() : pTxtFrm->GetTxtNode()->Len();
3373 }
3374
next()3375 const SwTxtAttr *SwHyperlinkIter_Impl::next()
3376 {
3377 const SwTxtAttr *pAttr = 0;
3378 if( pHints )
3379 {
3380 while( !pAttr && nPos < pHints->Count() )
3381 {
3382 const SwTxtAttr *pHt = (*pHints)[nPos];
3383 if( RES_TXTATR_INETFMT == pHt->Which() )
3384 {
3385 xub_StrLen nHtStt = *pHt->GetStart();
3386 xub_StrLen nHtEnd = *pHt->GetAnyEnd();
3387 if( nHtEnd > nHtStt &&
3388 ( (nHtStt >= nStt && nHtStt < nEnd) ||
3389 (nHtEnd > nStt && nHtEnd <= nEnd) ) )
3390 {
3391 pAttr = pHt;
3392 }
3393 }
3394 ++nPos;
3395 }
3396 }
3397
3398 return pAttr;
3399 };
3400
getHyperLinkCount()3401 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkCount()
3402 throw (uno::RuntimeException)
3403 {
3404 vos::OGuard aGuard(Application::GetSolarMutex());
3405
3406 CHECK_FOR_DEFUNC( XAccessibleHypertext );
3407
3408 sal_Int32 nCount = 0;
3409 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
3410 // if( !IsEditableState() )
3411 // <--
3412 {
3413 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3414 SwHyperlinkIter_Impl aIter( pTxtFrm );
3415 while( aIter.next() )
3416 nCount++;
3417 }
3418
3419 return nCount;
3420 }
3421
3422 uno::Reference< XAccessibleHyperlink > SAL_CALL
getHyperLink(sal_Int32 nLinkIndex)3423 SwAccessibleParagraph::getHyperLink( sal_Int32 nLinkIndex )
3424 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3425 {
3426 vos::OGuard aGuard(Application::GetSolarMutex());
3427 CHECK_FOR_DEFUNC( XAccessibleHypertext );
3428
3429 uno::Reference< XAccessibleHyperlink > xRet;
3430
3431 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
3432 // if( !IsEditableState() )
3433 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3434 SwHyperlinkIter_Impl aHIter( pTxtFrm );
3435 //SwAccessibleAutoRecognizerHelper_Impl aARHelper( pTxtFrm );
3436 sal_Int32 nARCount = 0;
3437 sal_Int32 nARIndex = 0;
3438 sal_Int32 nTIndex = -1;
3439 sal_Int32 nTOCEndIndex = -1;
3440 SwTxtNode* pNode = NULL;
3441 SwTOXSortTabBase* pTBase = GetTOXSortTabBase();
3442 if( pTBase )
3443 {
3444 pNode = const_cast<SwTxtNode*>(GetTxtNode());
3445 }
3446 nTOCEndIndex = -1;
3447 SwTxtAttr* pHt = (SwTxtAttr*)(aHIter.next());
3448 while( (nLinkIndex < getHyperLinkCount()) && nTIndex < nLinkIndex)
3449 {
3450 // no candidates, exit
3451 //if( (!pHt) && (nARIndex >= nARCount) && nTOCEndIndex <= 0)
3452 // break;
3453
3454 sal_Int32 nHStt = -1;
3455 sal_Int32 nAStt = -1;
3456 sal_Bool bH = sal_False;
3457 sal_Bool bA = sal_False;
3458
3459
3460 if( pHt )
3461 nHStt = *pHt->GetStart();
3462 if( nARIndex < nARCount )
3463 {
3464 /*
3465 sal_Int32 nAEnd;
3466 aARHelper.getPosition( nARIndex, nAStt, nAEnd );
3467 */
3468 }
3469 sal_Bool bTOC = sal_False;
3470 // Inside TOC & get the first link
3471 if( pTBase && nTIndex == -1 )
3472 {
3473 nTIndex++;
3474 bTOC = sal_True;
3475 }
3476 else
3477 {
3478 if( nHStt >=0 && nAStt >=0 )
3479 { // both hyperlink and smart tag available
3480 nTIndex++;
3481 if( nHStt <= nAStt )
3482 bH = sal_True;
3483 else
3484 bA = sal_True;
3485 }
3486 else if( nHStt >= 0 )
3487 { // only hyperlink available
3488 nTIndex++;
3489 bH = sal_True;
3490 }
3491 else if( nAStt >= 0 )
3492 { // only smart tag available
3493 nTIndex++;
3494 bA = sal_True;
3495 }
3496 }
3497
3498 if( nTIndex == nLinkIndex )
3499 { // found
3500 if( bH )
3501 { // it's a hyperlink
3502 if( pHt )
3503 {
3504 // const SwField* pFFld = pHt->GetFld().GetFld();
3505 {
3506 if( !pHyperTextData )
3507 pHyperTextData = new SwAccessibleHyperTextData;
3508 SwAccessibleHyperTextData::iterator aIter =
3509 pHyperTextData ->find( pHt );
3510 if( aIter != pHyperTextData->end() )
3511 {
3512 xRet = (*aIter).second;
3513 }
3514 if( !xRet.is() )
3515 {
3516 {
3517 const sal_Int32 nTmpHStt= GetPortionData().GetAccessiblePosition(
3518 max( aHIter.startIdx(), *pHt->GetStart() ) );
3519 const sal_Int32 nTmpHEnd= GetPortionData().GetAccessiblePosition(
3520 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
3521 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
3522 this, nTmpHStt, nTmpHEnd );
3523 }
3524 if( aIter != pHyperTextData->end() )
3525 {
3526 (*aIter).second = xRet;
3527 }
3528 else
3529 {
3530 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
3531 pHyperTextData->insert( aEntry );
3532 }
3533 }
3534 }
3535 }
3536 }
3537 else if( bTOC )
3538 {
3539 //xRet = new SwAccessibleTOCLink( this );
3540 }
3541 else if( bA )
3542 {
3543 /*
3544 // it's a smart tag
3545 if( !pAutoRecognizerData )
3546 pAutoRecognizerData = new SwAccessibleAutoRecognizerData;
3547 SwAccessibleAutoRecognizerData::iterator aIter =
3548 pAutoRecognizerData ->find( nARIndex );
3549 if( aIter != pAutoRecognizerData->end() )
3550 {
3551 xRet = (*aIter).second;
3552 }
3553 if( !xRet.is() )
3554 {
3555 sal_Int32 nAStt = 0;
3556 sal_Int32 nAEnd = 0;
3557 //aARHelper.getPosition( nARIndex, nAStt, nAEnd );
3558 xRet = new SwAccessibleAutoRecognizer( this, nAStt, nAEnd );
3559 if( aIter != pAutoRecognizerData->end() )
3560 {
3561 (*aIter).second = xRet;
3562 }
3563 else
3564 {
3565 SwAccessibleAutoRecognizerData::value_type aEntry( nARIndex, xRet );
3566 pAutoRecognizerData->insert( aEntry );
3567 }
3568 }
3569 */
3570 }
3571 break;
3572 }
3573
3574 // iterate next
3575 if( bH )
3576 // iterate next hyperlink
3577 pHt = (SwTxtAttr*)(aHIter.next());
3578 else if( bA )
3579 // iterate next smart tag
3580 nARIndex++;
3581 else if(bTOC)
3582 continue;
3583 else
3584 // no candidate, exit
3585 break;
3586 }
3587 /*
3588 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3589 SwHyperlinkIter_Impl aHIter( pTxtFrm );
3590 while( nLinkIndex-- )
3591 aHIter.next();
3592
3593 const SwTxtAttr *pHt = aHIter.next();
3594 if( pHt )
3595 {
3596 if( !pHyperTextData )
3597 pHyperTextData = new SwAccessibleHyperTextData;
3598 SwAccessibleHyperTextData::iterator aIter =
3599 pHyperTextData ->find( pHt );
3600 if( aIter != pHyperTextData->end() )
3601 {
3602 xRet = (*aIter).second;
3603 }
3604 if( !xRet.is() )
3605 {
3606 sal_Int32 nHStt= GetPortionData().GetAccessiblePosition(
3607 max( aHIter.startIdx(), *pHt->GetStart() ) );
3608 sal_Int32 nHEnd= GetPortionData().GetAccessiblePosition(
3609 min( aHIter.endIdx(), *pHt->GetAnyEnd() ) );
3610 xRet = new SwAccessibleHyperlink( aHIter.getCurrHintPos(),
3611 this, nHStt, nHEnd );
3612 if( aIter != pHyperTextData->end() )
3613 {
3614 (*aIter).second = xRet;
3615 }
3616 else
3617 {
3618 SwAccessibleHyperTextData::value_type aEntry( pHt, xRet );
3619 pHyperTextData->insert( aEntry );
3620 }
3621 }
3622 }
3623 }
3624 */
3625 if( !xRet.is() )
3626 throw lang::IndexOutOfBoundsException();
3627
3628 return xRet;
3629 }
3630
getHyperLinkIndex(sal_Int32 nCharIndex)3631 sal_Int32 SAL_CALL SwAccessibleParagraph::getHyperLinkIndex( sal_Int32 nCharIndex )
3632 throw (lang::IndexOutOfBoundsException, uno::RuntimeException)
3633 {
3634 vos::OGuard aGuard(Application::GetSolarMutex());
3635 CHECK_FOR_DEFUNC( XAccessibleHypertext );
3636
3637 // parameter checking
3638 sal_Int32 nLength = GetString().getLength();
3639 if ( ! IsValidPosition( nCharIndex, nLength ) )
3640 {
3641 throw lang::IndexOutOfBoundsException();
3642 }
3643
3644 sal_Int32 nRet = -1;
3645 // --> OD 2007-06-27 #i77108# - provide hyperlinks also in editable documents.
3646 // if( !IsEditableState() )
3647 // <--
3648 {
3649 const SwTxtFrm *pTxtFrm = static_cast<const SwTxtFrm*>( GetFrm() );
3650 SwHyperlinkIter_Impl aHIter( pTxtFrm );
3651
3652 xub_StrLen nIdx = GetPortionData().GetModelPosition( nCharIndex );
3653 sal_Int32 nPos = 0;
3654 const SwTxtAttr *pHt = aHIter.next();
3655 while( pHt && !(nIdx >= *pHt->GetStart() && nIdx < *pHt->GetAnyEnd()) )
3656 {
3657 pHt = aHIter.next();
3658 nPos++;
3659 }
3660
3661 if( pHt )
3662 nRet = nPos;
3663 }
3664
3665 if (nRet == -1)
3666 throw lang::IndexOutOfBoundsException();
3667 else
3668 return nRet;
3669 //return nRet;
3670 }
3671
3672 // --> OD 2008-05-26 #i71360#
3673 // --> OD 2010-02-22 #i108125# - adjustments for change tracking text markup
getTextMarkupCount(sal_Int32 nTextMarkupType)3674 sal_Int32 SAL_CALL SwAccessibleParagraph::getTextMarkupCount( sal_Int32 nTextMarkupType )
3675 throw (lang::IllegalArgumentException,
3676 uno::RuntimeException)
3677 {
3678 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3679 switch ( nTextMarkupType )
3680 {
3681 case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3682 case text::TextMarkupType::TRACK_CHANGE_DELETION:
3683 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3684 {
3685 pTextMarkupHelper.reset( new SwTextMarkupHelper(
3686 GetPortionData(),
3687 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3688 }
3689 break;
3690 default:
3691 {
3692 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
3693 }
3694 }
3695
3696 return pTextMarkupHelper->getTextMarkupCount( nTextMarkupType );
3697 }
3698 //MSAA Extension Implementation in app module
scrollToPosition(const::com::sun::star::awt::Point &,sal_Bool)3699 sal_Bool SAL_CALL SwAccessibleParagraph::scrollToPosition( const ::com::sun::star::awt::Point&, sal_Bool )
3700 throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
3701 {
3702 return sal_False;
3703 }
3704
getSelectedPortionCount()3705 sal_Int32 SAL_CALL SwAccessibleParagraph::getSelectedPortionCount( )
3706 throw (::com::sun::star::uno::RuntimeException)
3707 {
3708 sal_Int32 nSeleted = 0;
3709 SwPaM* pCrsr = GetCursor( true );
3710 if( pCrsr != NULL )
3711 {
3712 // get SwPosition for my node
3713 const SwTxtNode* pNode = GetTxtNode();
3714 sal_uLong nHere = pNode->GetIndex();
3715
3716 // iterate over ring
3717 SwPaM* pRingStart = pCrsr;
3718 do
3719 {
3720 // ignore, if no mark
3721 if( pCrsr->HasMark() )
3722 {
3723 // check whether nHere is 'inside' pCrsr
3724 SwPosition* pStart = pCrsr->Start();
3725 sal_uLong nStartIndex = pStart->nNode.GetIndex();
3726 SwPosition* pEnd = pCrsr->End();
3727 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3728 if( ( nHere >= nStartIndex ) &&
3729 ( nHere <= nEndIndex ) )
3730 {
3731 nSeleted++;
3732 }
3733 // else: this PaM doesn't point to this paragraph
3734 }
3735 // else: this PaM is collapsed and doesn't select anything
3736
3737 // next PaM in ring
3738 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3739 }
3740 while( pCrsr != pRingStart );
3741 }
3742 return nSeleted;
3743
3744 }
3745
getSeletedPositionStart(sal_Int32 nSelectedPortionIndex)3746 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionStart( sal_Int32 nSelectedPortionIndex )
3747 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3748 {
3749 vos::OGuard aGuard(Application::GetSolarMutex());
3750
3751 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3752
3753 sal_Int32 nStart, nEnd;
3754 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3755 return nStart;
3756 }
3757
getSeletedPositionEnd(sal_Int32 nSelectedPortionIndex)3758 sal_Int32 SAL_CALL SwAccessibleParagraph::getSeletedPositionEnd( sal_Int32 nSelectedPortionIndex )
3759 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3760 {
3761 vos::OGuard aGuard(Application::GetSolarMutex());
3762
3763 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3764
3765 sal_Int32 nStart, nEnd;
3766 /*sal_Bool bSelected = */GetSelectionAtIndex(nSelectedPortionIndex, nStart, nEnd );
3767 return nEnd;
3768 }
3769
removeSelection(sal_Int32 selectionIndex)3770 sal_Bool SAL_CALL SwAccessibleParagraph::removeSelection( sal_Int32 selectionIndex )
3771 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3772 {
3773 if(selectionIndex < 0) return sal_False;
3774
3775 sal_Bool bRet = sal_False;
3776 sal_Int32 nSelected = selectionIndex;
3777
3778 // get the selection, and test whether it affects our text node
3779 SwPaM* pCrsr = GetCursor( true );
3780 // SwPaM* pFirst = pCrsr;
3781 SwPaM* pPrev = pCrsr;
3782
3783 if( pCrsr != NULL )
3784 {
3785 // get SwPosition for my node
3786 const SwTxtNode* pNode = GetTxtNode();
3787 sal_uLong nHere = pNode->GetIndex();
3788
3789 // iterate over ring
3790 SwPaM* pRingStart = pCrsr;
3791 do
3792 {
3793 // ignore, if no mark
3794 if( pCrsr->HasMark() )
3795 {
3796 // check whether nHere is 'inside' pCrsr
3797 SwPosition* pStart = pCrsr->Start();
3798 sal_uLong nStartIndex = pStart->nNode.GetIndex();
3799 SwPosition* pEnd = pCrsr->End();
3800 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
3801 if( ( nHere >= nStartIndex ) &&
3802 ( nHere <= nEndIndex ) )
3803 {
3804 if( nSelected == 0 )
3805 {
3806 pCrsr->MoveTo((Ring*)0);
3807 delete pCrsr;
3808 bRet = sal_True;
3809 }
3810 else
3811 {
3812 nSelected--;
3813 }
3814 }
3815 }
3816 // else: this PaM is collapsed and doesn't select anything
3817 pPrev = pCrsr;
3818 if(!bRet)
3819 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
3820 }
3821 while( !bRet && (pCrsr != pRingStart) );
3822 }
3823 return sal_True;
3824 }
3825
addSelection(sal_Int32,sal_Int32 startOffset,sal_Int32 endOffset)3826 sal_Int32 SAL_CALL SwAccessibleParagraph::addSelection( sal_Int32, sal_Int32 startOffset, sal_Int32 endOffset)
3827 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
3828 {
3829 vos::OGuard aGuard(Application::GetSolarMutex());
3830
3831 CHECK_FOR_DEFUNC_THIS( XAccessibleText, *this );
3832
3833 // parameter checking
3834 sal_Int32 nLength = GetString().getLength();
3835 if ( ! IsValidRange( startOffset, endOffset, nLength ) )
3836 {
3837 throw lang::IndexOutOfBoundsException();
3838 }
3839
3840 sal_Int32 nSelectedCount = getSelectedPortionCount();
3841 for ( sal_Int32 i = nSelectedCount ; i >= 0 ; i--)
3842 {
3843 sal_Int32 nStart, nEnd;
3844 sal_Bool bSelected = GetSelectionAtIndex(i, nStart, nEnd );
3845 if(bSelected)
3846 {
3847 if(nStart <= nEnd )
3848 {
3849 if (( startOffset>=nStart && startOffset <=nEnd ) || //startOffset in a selection
3850 ( endOffset>=nStart && endOffset <=nEnd ) || //endOffset in a selection
3851 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection
3852 ( startOffset >= nStart && endOffset <=nEnd) )
3853 {
3854 removeSelection(i);
3855 }
3856
3857 }
3858 else
3859 {
3860 if (( startOffset>=nEnd && startOffset <=nStart ) || //startOffset in a selection
3861 ( endOffset>=nEnd && endOffset <=nStart ) || //endOffset in a selection
3862 ( startOffset <= nStart && endOffset >=nEnd) || //start and end include the old selection
3863 ( startOffset >= nStart && endOffset <=nEnd) )
3864
3865 {
3866 removeSelection(i);
3867 }
3868 }
3869 }
3870
3871 }
3872
3873 sal_Bool bRet = sal_False;
3874
3875 // get cursor shell
3876 SwCrsrShell* pCrsrShell = GetCrsrShell();
3877 if( pCrsrShell != NULL )
3878 {
3879 // create pam for selection
3880 pCrsrShell->StartAction();
3881 // SwTxtNode* pNode = const_cast<SwTxtNode*>( GetTxtNode() );
3882 SwPaM* aPaM = pCrsrShell->CreateCrsr();
3883 aPaM->SetMark();
3884 aPaM->GetPoint()->nContent = GetPortionData().GetModelPosition(startOffset);
3885 aPaM->GetMark()->nContent = GetPortionData().GetModelPosition(endOffset);
3886 //pCrsrShell->ShowCrsr();
3887 pCrsrShell->EndAction();
3888 // set PaM at cursor shell
3889 //bRet = Select( aPaM );
3890 }
3891
3892 return bRet;
3893 }
3894
3895 /*accessibility::*/TextSegment SAL_CALL
getTextMarkup(sal_Int32 nTextMarkupIndex,sal_Int32 nTextMarkupType)3896 SwAccessibleParagraph::getTextMarkup( sal_Int32 nTextMarkupIndex,
3897 sal_Int32 nTextMarkupType )
3898 throw (lang::IndexOutOfBoundsException,
3899 lang::IllegalArgumentException,
3900 uno::RuntimeException)
3901 {
3902 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3903 switch ( nTextMarkupType )
3904 {
3905 case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3906 case text::TextMarkupType::TRACK_CHANGE_DELETION:
3907 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3908 {
3909 pTextMarkupHelper.reset( new SwTextMarkupHelper(
3910 GetPortionData(),
3911 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3912 }
3913 break;
3914 default:
3915 {
3916 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
3917 }
3918 }
3919
3920 return pTextMarkupHelper->getTextMarkup( nTextMarkupIndex, nTextMarkupType );
3921 }
3922
3923 uno::Sequence< /*accessibility::*/TextSegment > SAL_CALL
getTextMarkupAtIndex(sal_Int32 nCharIndex,sal_Int32 nTextMarkupType)3924 SwAccessibleParagraph::getTextMarkupAtIndex( sal_Int32 nCharIndex,
3925 sal_Int32 nTextMarkupType )
3926 throw (lang::IndexOutOfBoundsException,
3927 lang::IllegalArgumentException,
3928 uno::RuntimeException)
3929 {
3930 // parameter checking
3931 const sal_Int32 nLength = GetString().getLength();
3932 if ( ! IsValidPosition( nCharIndex, nLength ) )
3933 {
3934 throw lang::IndexOutOfBoundsException();
3935 }
3936
3937 std::auto_ptr<SwTextMarkupHelper> pTextMarkupHelper;
3938 switch ( nTextMarkupType )
3939 {
3940 case text::TextMarkupType::TRACK_CHANGE_INSERTION:
3941 case text::TextMarkupType::TRACK_CHANGE_DELETION:
3942 case text::TextMarkupType::TRACK_CHANGE_FORMATCHANGE:
3943 {
3944 pTextMarkupHelper.reset( new SwTextMarkupHelper(
3945 GetPortionData(),
3946 *(mpParaChangeTrackInfo->getChangeTrackingTextMarkupList( nTextMarkupType ) )) );
3947 }
3948 break;
3949 default:
3950 {
3951 pTextMarkupHelper.reset( new SwTextMarkupHelper( GetPortionData(), *GetTxtNode() ) );
3952 }
3953 }
3954
3955 return pTextMarkupHelper->getTextMarkupAtIndex( nCharIndex, nTextMarkupType );
3956 }
3957 // <--
3958
3959 // --> OD 2008-05-29 #i89175#
getLineNumberAtIndex(sal_Int32 nIndex)3960 sal_Int32 SAL_CALL SwAccessibleParagraph::getLineNumberAtIndex( sal_Int32 nIndex )
3961 throw (lang::IndexOutOfBoundsException,
3962 uno::RuntimeException)
3963 {
3964 // parameter checking
3965 const sal_Int32 nLength = GetString().getLength();
3966 if ( ! IsValidPosition( nIndex, nLength ) )
3967 {
3968 throw lang::IndexOutOfBoundsException();
3969 }
3970
3971 const sal_Int32 nLineNo = GetPortionData().GetLineNo( nIndex );
3972 return nLineNo;
3973 }
3974
3975 /*accessibility::*/TextSegment SAL_CALL
getTextAtLineNumber(sal_Int32 nLineNo)3976 SwAccessibleParagraph::getTextAtLineNumber( sal_Int32 nLineNo )
3977 throw (lang::IndexOutOfBoundsException,
3978 uno::RuntimeException)
3979 {
3980 // parameter checking
3981 if ( nLineNo < 0 ||
3982 nLineNo >= GetPortionData().GetLineCount() )
3983 {
3984 throw lang::IndexOutOfBoundsException();
3985 }
3986
3987 i18n::Boundary aLineBound;
3988 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
3989
3990 /*accessibility::*/TextSegment aTextAtLine;
3991 const ::rtl::OUString rText = GetString();
3992 aTextAtLine.SegmentText = rText.copy( aLineBound.startPos,
3993 aLineBound.endPos - aLineBound.startPos );
3994 aTextAtLine.SegmentStart = aLineBound.startPos;
3995 aTextAtLine.SegmentEnd = aLineBound.endPos;
3996
3997 return aTextAtLine;
3998 }
3999
getTextAtLineWithCaret()4000 /*accessibility::*/TextSegment SAL_CALL SwAccessibleParagraph::getTextAtLineWithCaret()
4001 throw (uno::RuntimeException)
4002 {
4003 const sal_Int32 nLineNoOfCaret = getNumberOfLineWithCaret();
4004
4005 if ( nLineNoOfCaret >= 0 &&
4006 nLineNoOfCaret < GetPortionData().GetLineCount() )
4007 {
4008 return getTextAtLineNumber( nLineNoOfCaret );
4009 }
4010
4011 return /*accessibility::*/TextSegment();
4012 }
4013
getNumberOfLineWithCaret()4014 sal_Int32 SAL_CALL SwAccessibleParagraph::getNumberOfLineWithCaret()
4015 throw (uno::RuntimeException)
4016 {
4017 const sal_Int32 nCaretPos = getCaretPosition();
4018 const sal_Int32 nLength = GetString().getLength();
4019 if ( !IsValidPosition( nCaretPos, nLength ) )
4020 {
4021 return -1;
4022 }
4023
4024 sal_Int32 nLineNo = GetPortionData().GetLineNo( nCaretPos );
4025
4026 // special handling for cursor positioned at end of text line via End key
4027 if ( nCaretPos != 0 )
4028 {
4029 i18n::Boundary aLineBound;
4030 GetPortionData().GetBoundaryOfLine( nLineNo, aLineBound );
4031 if ( nCaretPos == aLineBound.startPos )
4032 {
4033 SwCrsrShell* pCrsrShell = SwAccessibleParagraph::GetCrsrShell();
4034 if ( pCrsrShell != 0 )
4035 {
4036 const awt::Rectangle aCharRect = getCharacterBounds( nCaretPos );
4037
4038 const SwRect& aCursorCoreRect = pCrsrShell->GetCharRect();
4039 // translate core coordinates into accessibility coordinates
4040 Window *pWin = GetWindow();
4041 CHECK_FOR_WINDOW( XAccessibleComponent, pWin );
4042
4043 Rectangle aScreenRect( GetMap()->CoreToPixel( aCursorCoreRect.SVRect() ));
4044
4045 SwRect aFrmLogBounds( GetBounds( *(GetMap()) ) ); // twip rel to doc root
4046 Point aFrmPixPos( GetMap()->CoreToPixel( aFrmLogBounds.SVRect() ).TopLeft() );
4047 aScreenRect.Move( -aFrmPixPos.X(), -aFrmPixPos.Y() );
4048
4049 // convert into AWT Rectangle
4050 const awt::Rectangle aCursorRect( aScreenRect.Left(),
4051 aScreenRect.Top(),
4052 aScreenRect.GetWidth(),
4053 aScreenRect.GetHeight() );
4054
4055 if ( aCharRect.X != aCursorRect.X ||
4056 aCharRect.Y != aCursorRect.Y )
4057 {
4058 --nLineNo;
4059 }
4060 }
4061 }
4062 }
4063
4064 return nLineNo;
4065 }
4066
4067 // --> OD 2010-02-19 #i108125#
Modify(const SfxPoolItem * pOld,const SfxPoolItem * pNew)4068 void SwAccessibleParagraph::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
4069 {
4070 mpParaChangeTrackInfo->reset();
4071
4072 CheckRegistration( pOld, pNew );
4073 }
4074 // <--
4075
GetSelectionAtIndex(sal_Int32 & nIndex,sal_Int32 & nStart,sal_Int32 & nEnd)4076 sal_Bool SwAccessibleParagraph::GetSelectionAtIndex(
4077 sal_Int32& nIndex, sal_Int32& nStart, sal_Int32& nEnd)
4078 {
4079 if(nIndex < 0) return sal_False;
4080
4081
4082 sal_Bool bRet = sal_False;
4083 nStart = -1;
4084 nEnd = -1;
4085 sal_Int32 nSelected = nIndex;
4086
4087 // get the selection, and test whether it affects our text node
4088 SwPaM* pCrsr = GetCursor( true );
4089 if( pCrsr != NULL )
4090 {
4091 // get SwPosition for my node
4092 const SwTxtNode* pNode = GetTxtNode();
4093 sal_uLong nHere = pNode->GetIndex();
4094
4095 // iterate over ring
4096 SwPaM* pRingStart = pCrsr;
4097 do
4098 {
4099 // ignore, if no mark
4100 if( pCrsr->HasMark() )
4101 {
4102 // check whether nHere is 'inside' pCrsr
4103 SwPosition* pStart = pCrsr->Start();
4104 sal_uLong nStartIndex = pStart->nNode.GetIndex();
4105 SwPosition* pEnd = pCrsr->End();
4106 sal_uLong nEndIndex = pEnd->nNode.GetIndex();
4107 if( ( nHere >= nStartIndex ) &&
4108 ( nHere <= nEndIndex ) )
4109 {
4110 if( nSelected == 0 )
4111 {
4112 // translate start and end positions
4113
4114 // start position
4115 sal_Int32 nLocalStart = -1;
4116 if( nHere > nStartIndex )
4117 {
4118 // selection starts in previous node:
4119 // then our local selection starts with the paragraph
4120 nLocalStart = 0;
4121 }
4122 else
4123 {
4124 DBG_ASSERT( nHere == nStartIndex,
4125 "miscalculated index" );
4126
4127 // selection starts in this node:
4128 // then check whether it's before or inside our part of
4129 // the paragraph, and if so, get the proper position
4130 sal_uInt16 nCoreStart = pStart->nContent.GetIndex();
4131 if( nCoreStart <
4132 GetPortionData().GetFirstValidCorePosition() )
4133 {
4134 nLocalStart = 0;
4135 }
4136 else if( nCoreStart <=
4137 GetPortionData().GetLastValidCorePosition() )
4138 {
4139 DBG_ASSERT(
4140 GetPortionData().IsValidCorePosition(
4141 nCoreStart ),
4142 "problem determining valid core position" );
4143
4144 nLocalStart =
4145 GetPortionData().GetAccessiblePosition(
4146 nCoreStart );
4147 }
4148 }
4149
4150 // end position
4151 sal_Int32 nLocalEnd = -1;
4152 if( nHere < nEndIndex )
4153 {
4154 // selection ends in following node:
4155 // then our local selection extends to the end
4156 nLocalEnd = GetPortionData().GetAccessibleString().
4157 getLength();
4158 }
4159 else
4160 {
4161 DBG_ASSERT( nHere == nStartIndex,
4162 "miscalculated index" );
4163
4164 // selection ends in this node: then select everything
4165 // before our part of the node
4166 sal_uInt16 nCoreEnd = pEnd->nContent.GetIndex();
4167 if( nCoreEnd >
4168 GetPortionData().GetLastValidCorePosition() )
4169 {
4170 // selection extends beyond out part of this para
4171 nLocalEnd = GetPortionData().GetAccessibleString().
4172 getLength();
4173 }
4174 else if( nCoreEnd >=
4175 GetPortionData().GetFirstValidCorePosition() )
4176 {
4177 // selection is inside our part of this para
4178 DBG_ASSERT(
4179 GetPortionData().IsValidCorePosition(
4180 nCoreEnd ),
4181 "problem determining valid core position" );
4182
4183 nLocalEnd = GetPortionData().GetAccessiblePosition(
4184 nCoreEnd );
4185 }
4186 }
4187
4188 if( ( nLocalStart != -1 ) && ( nLocalEnd != -1 ) )
4189 {
4190 nStart = nLocalStart;
4191 nEnd = nLocalEnd;
4192 bRet = sal_True;
4193 }
4194 } // if hit the index
4195 else
4196 {
4197 nSelected--;
4198 }
4199 }
4200 // else: this PaM doesn't point to this paragraph
4201 }
4202 // else: this PaM is collapsed and doesn't select anything
4203
4204 // next PaM in ring
4205 pCrsr = static_cast<SwPaM*>( pCrsr->GetNext() );
4206 }
4207 while( !bRet && (pCrsr != pRingStart) );
4208 }
4209 // else: nocursor -> no selection
4210
4211 if( bRet )
4212 {
4213 sal_Int32 nCaretPos = GetCaretPos();
4214 if( nStart == nCaretPos )
4215 {
4216 sal_Int32 tmp = nStart;
4217 nStart = nEnd;
4218 nEnd = tmp;
4219 }
4220 }
4221 return bRet;
4222 }
4223
getAccessibleRole(void)4224 sal_Int16 SAL_CALL SwAccessibleParagraph::getAccessibleRole (void) throw (::com::sun::star::uno::RuntimeException)
4225 {
4226 //Get the real heading level, Heading1 ~ Heading10
4227 if (nHeadingLevel > 0)
4228 {
4229 return AccessibleRole::HEADING;
4230 }
4231 else
4232 {
4233 return AccessibleRole::PARAGRAPH;
4234 }
4235 }
4236
4237
4238 //Get the real heading level, Heading1 ~ Heading10
GetRealHeadingLevel()4239 sal_Int32 SwAccessibleParagraph::GetRealHeadingLevel()
4240 {
4241 uno::Reference< ::com::sun::star::beans::XPropertySet > xPortion = CreateUnoPortion( 0, 0 );
4242 ::rtl::OUString pString = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ParaStyleName"));
4243 uno::Any styleAny = xPortion->getPropertyValue( pString );
4244 ::rtl::OUString sValue;
4245 if (styleAny >>= sValue)
4246 {
4247 sal_Int32 length = sValue.getLength();
4248 if (length == 9 || length == 10)
4249 {
4250 ::rtl::OUString headStr = sValue.copy(0, 7);
4251 if (headStr.equals(::rtl::OUString::createFromAscii("Heading")))
4252 {
4253 ::rtl::OUString intStr = sValue.copy(8);
4254 sal_Int32 headingLevel = intStr.toInt32(10);
4255 return headingLevel;
4256 }
4257 }
4258 }
4259 return -1;
4260 }
4261
getExtendedAttributes()4262 uno::Any SAL_CALL SwAccessibleParagraph::getExtendedAttributes()
4263 throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException)
4264 {
4265 uno::Any Ret;
4266 ::rtl::OUString strHeading(::rtl::OUString::createFromAscii("heading-level:"));
4267 if( nHeadingLevel >= 0 )
4268 strHeading += OUString::valueOf(nHeadingLevel, 10);
4269 strHeading += OUString::createFromAscii(";");
4270
4271 Ret <<= strHeading;
4272
4273 return Ret;
4274 }
4275
4276 //Tab will be return when call WORDTYPE
tabCharInWord(sal_Int32 nIndex,i18n::Boundary & aBound)4277 sal_Bool SwAccessibleParagraph::tabCharInWord( sal_Int32 nIndex, i18n::Boundary& aBound)
4278 {
4279 sal_Bool bFind = sal_False;
4280 if( aBound.startPos != nIndex)
4281 {
4282 OUString tabStr;
4283 if(aBound.startPos>nIndex)
4284 tabStr = GetString().copy(nIndex,(aBound.startPos - nIndex) );
4285
4286 sal_Unicode tabChar('\t');
4287 sal_Int32 tabIndex = tabStr.indexOf(tabChar);
4288 if( tabIndex > -1 )
4289 {
4290 aBound.startPos = nIndex + tabIndex ;
4291 aBound.endPos = aBound.startPos + 1;
4292 bFind = sal_True;
4293 }
4294 }
4295 return bFind;
4296 }
4297