bump product version to 5.0.4.1
[LibreOffice.git] / editeng / source / accessibility / AccessibleEditableTextPara.cxx
blobf2714fb01023440bea9fd037ff4373acde76053a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
23 // Global header
27 #include <limits.h>
28 #include <vector>
29 #include <algorithm>
30 #include <osl/mutex.hxx>
31 #include <vcl/window.hxx>
32 #include <vcl/svapp.hxx>
33 #include <editeng/flditem.hxx>
34 #include <com/sun/star/uno/Any.hxx>
35 #include <com/sun/star/uno/Reference.hxx>
36 #include <com/sun/star/awt/Point.hpp>
37 #include <com/sun/star/awt/Rectangle.hpp>
38 #include <com/sun/star/lang/DisposedException.hpp>
39 #include <com/sun/star/accessibility/AccessibleRole.hpp>
40 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
41 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
42 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
43 #include <comphelper/accessibleeventnotifier.hxx>
44 #include <comphelper/sequenceashashmap.hxx>
45 #include <cppuhelper/supportsservice.hxx>
46 #include <unotools/accessiblestatesethelper.hxx>
47 #include <unotools/accessiblerelationsethelper.hxx>
48 #include <com/sun/star/accessibility/AccessibleRelationType.hpp>
49 #include <vcl/unohelp.hxx>
50 #include <vcl/settings.hxx>
52 #include <editeng/editeng.hxx>
53 #include <editeng/unoprnms.hxx>
54 #include <editeng/unoipset.hxx>
55 #include <editeng/outliner.hxx>
56 #include <svl/intitem.hxx>
60 // Project-local header
64 #include <com/sun/star/beans/PropertyState.hpp>
66 #include <editeng/unolingu.hxx>
67 #include <editeng/unopracc.hxx>
68 #include "editeng/AccessibleEditableTextPara.hxx"
69 #include "AccessibleHyperlink.hxx"
71 #include <svtools/colorcfg.hxx>
72 using namespace std;
73 #include "editeng.hrc"
74 #include <editeng/eerdll.hxx>
75 #include <editeng/numitem.hxx>
76 #include <boost/scoped_array.hpp>
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::beans;
80 using namespace ::com::sun::star::accessibility;
84 // AccessibleEditableTextPara implementation
88 namespace accessibility
90 const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet()
92 // PropertyMap for character and paragraph properties
93 static const SfxItemPropertyMapEntry aPropMap[] =
95 SVX_UNOEDIT_OUTLINER_PROPERTIES,
96 SVX_UNOEDIT_CHAR_PROPERTIES,
97 SVX_UNOEDIT_PARA_PROPERTIES,
98 SVX_UNOEDIT_NUMBERING_PROPERTIE,
99 {OUString("TextUserDefinedAttributes"), EE_CHAR_XMLATTRIBS, cppu::UnoType<com::sun::star::container::XNameContainer>::get(), 0, 0},
100 {OUString("ParaUserDefinedAttributes"), EE_PARA_XMLATTRIBS, cppu::UnoType<com::sun::star::container::XNameContainer>::get(), 0, 0},
101 { OUString(), 0, css::uno::Type(), 0, 0 }
103 static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() );
104 return &aPropSet;
107 // #i27138# - add parameter <_pParaManager>
108 AccessibleEditableTextPara::AccessibleEditableTextPara(
109 const uno::Reference< XAccessible >& rParent,
110 const AccessibleParaManager* _pParaManager )
111 : AccessibleTextParaInterfaceBase( m_aMutex ),
112 mnParagraphIndex( 0 ),
113 mnIndexInParent( 0 ),
114 mpEditSource( NULL ),
115 maEEOffset( 0, 0 ),
116 mxParent( rParent ),
117 // well, that's strictly (UNO) exception safe, though not
118 // really robust. We rely on the fact that this member is
119 // constructed last, and that the constructor body catches
120 // exceptions, thus no chance for exceptions once the Id is
121 // fetched. Nevertheless, normally should employ RAII here...
122 mnNotifierClientId(::comphelper::AccessibleEventNotifier::registerClient()),
123 // #i27138#
124 mpParaManager( _pParaManager )
126 #ifdef DBG_UTIL
127 OSL_TRACE( "AccessibleEditableTextPara received ID: %d", mnNotifierClientId );
128 #endif
132 // Create the state set.
133 ::utl::AccessibleStateSetHelper* pStateSet = new ::utl::AccessibleStateSetHelper ();
134 mxStateSet = pStateSet;
136 // these are always on
137 pStateSet->AddState( AccessibleStateType::MULTI_LINE );
138 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
139 pStateSet->AddState( AccessibleStateType::VISIBLE );
140 pStateSet->AddState( AccessibleStateType::SHOWING );
141 pStateSet->AddState( AccessibleStateType::ENABLED );
142 pStateSet->AddState( AccessibleStateType::SENSITIVE );
144 catch (const uno::Exception&)
149 AccessibleEditableTextPara::~AccessibleEditableTextPara()
151 // sign off from event notifier
152 if( getNotifierClientId() != -1 )
156 ::comphelper::AccessibleEventNotifier::revokeClient( getNotifierClientId() );
157 #ifdef DBG_UTIL
158 OSL_TRACE( "AccessibleEditableTextPara revoked ID: %d", mnNotifierClientId );
159 #endif
161 catch (const uno::Exception&)
167 OUString AccessibleEditableTextPara::implGetText()
169 return GetTextRange( 0, GetTextLen() );
172 ::com::sun::star::lang::Locale AccessibleEditableTextPara::implGetLocale()
174 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
175 "AccessibleEditableTextPara::getLocale: paragraph index value overflow");
177 // return locale of first character in the paragraph
178 return LanguageTag(GetTextForwarder().GetLanguage( GetParagraphIndex(), 0 )).getLocale();
181 void AccessibleEditableTextPara::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
183 sal_Int32 nStart, nEnd;
185 if( GetSelection( nStart, nEnd ) )
187 nStartIndex = nStart;
188 nEndIndex = nEnd;
190 else
192 // #102234# No exception, just set to 'invalid'
193 nStartIndex = -1;
194 nEndIndex = -1;
198 void AccessibleEditableTextPara::implGetParagraphBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 /*nIndex*/ )
200 DBG_WARNING( "AccessibleEditableTextPara::implGetParagraphBoundary: only a base implementation, ignoring the index" );
202 rBoundary.startPos = 0;
203 //rBoundary.endPos = GetTextLen();
204 OUString sText( implGetText() );
205 sal_Int32 nLength = sText.getLength();
206 rBoundary.endPos = nLength;
209 void AccessibleEditableTextPara::implGetLineBoundary( ::com::sun::star::i18n::Boundary& rBoundary, sal_Int32 nIndex )
211 SvxTextForwarder& rCacheTF = GetTextForwarder();
212 const sal_Int32 nParaIndex = GetParagraphIndex();
214 DBG_ASSERT(nParaIndex >= 0 && nParaIndex <= SAL_MAX_INT32,
215 "AccessibleEditableTextPara::implGetLineBoundary: paragraph index value overflow");
217 const sal_Int32 nTextLen = rCacheTF.GetTextLen( nParaIndex );
219 CheckPosition(nIndex);
221 rBoundary.startPos = rBoundary.endPos = -1;
223 const sal_Int32 nLineCount=rCacheTF.GetLineCount( nParaIndex );
225 if( nIndex == nTextLen )
227 // #i17014# Special-casing one-behind-the-end character
228 if( nLineCount <= 1 )
229 rBoundary.startPos = 0;
230 else
231 rBoundary.startPos = nTextLen - rCacheTF.GetLineLen( nParaIndex,
232 nLineCount-1 );
234 rBoundary.endPos = nTextLen;
236 else
238 // normal line search
239 sal_Int32 nLine;
240 sal_Int32 nCurIndex;
241 for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
243 nCurIndex += rCacheTF.GetLineLen( nParaIndex, nLine);
245 if( nCurIndex > nIndex )
247 rBoundary.startPos = nCurIndex - rCacheTF.GetLineLen( nParaIndex, nLine);
248 rBoundary.endPos = nCurIndex;
249 break;
256 void AccessibleEditableTextPara::SetIndexInParent( sal_Int32 nIndex )
258 mnIndexInParent = nIndex;
262 void AccessibleEditableTextPara::SetParagraphIndex( sal_Int32 nIndex )
264 sal_Int32 nOldIndex = mnParagraphIndex;
266 mnParagraphIndex = nIndex;
268 WeakBullet::HardRefType aChild( maImageBullet.get() );
269 if( aChild.is() )
270 aChild->SetParagraphIndex(mnParagraphIndex);
274 if( nOldIndex != nIndex )
276 uno::Any aOldDesc;
277 uno::Any aOldName;
281 aOldDesc <<= getAccessibleDescription();
282 aOldName <<= getAccessibleName();
284 catch (const uno::Exception&) // optional behaviour
287 // index and therefore description changed
288 FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::makeAny( getAccessibleDescription() ), aOldDesc );
289 FireEvent( AccessibleEventId::NAME_CHANGED, uno::makeAny( getAccessibleName() ), aOldName );
292 catch (const uno::Exception&) // optional behaviour
298 void AccessibleEditableTextPara::Dispose()
300 int nClientId( getNotifierClientId() );
302 // #108212# drop all references before notifying dispose
303 mxParent = NULL;
304 mnNotifierClientId = -1;
305 mpEditSource = NULL;
307 // notify listeners
308 if( nClientId != -1 )
312 uno::Reference < XAccessibleContext > xThis = getAccessibleContext();
314 // #106234# Delegate to EventNotifier
315 ::comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, xThis );
316 #ifdef DBG_UTIL
317 OSL_TRACE( "Disposed ID: %d", nClientId );
318 #endif
320 catch (const uno::Exception&)
326 void AccessibleEditableTextPara::SetEditSource( SvxEditSourceAdapter* pEditSource )
328 WeakBullet::HardRefType aChild( maImageBullet.get() );
329 if( aChild.is() )
330 aChild->SetEditSource(pEditSource);
332 if( !pEditSource )
334 // going defunc
335 UnSetState( AccessibleStateType::SHOWING );
336 UnSetState( AccessibleStateType::VISIBLE );
337 SetState( AccessibleStateType::INVALID );
338 SetState( AccessibleStateType::DEFUNC );
340 Dispose();
342 mpEditSource = pEditSource;
343 // #108900# Init last text content
346 TextChanged();
348 catch (const uno::RuntimeException&)
353 ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex )
355 // check overflow
356 DBG_ASSERT(nStartEEIndex >= 0 && nStartEEIndex <= USHRT_MAX &&
357 nEndEEIndex >= 0 && nEndEEIndex <= USHRT_MAX &&
358 GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
359 "AccessibleEditableTextPara::MakeSelection: index value overflow");
361 sal_Int32 nParaIndex = GetParagraphIndex();
362 return ESelection(nParaIndex, nStartEEIndex, nParaIndex, nEndEEIndex);
365 ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nEEIndex )
367 return MakeSelection( nEEIndex, nEEIndex+1 );
370 ESelection AccessibleEditableTextPara::MakeCursor( sal_Int32 nEEIndex )
372 return MakeSelection( nEEIndex, nEEIndex );
375 void AccessibleEditableTextPara::CheckIndex( sal_Int32 nIndex )
377 if( nIndex < 0 || nIndex >= getCharacterCount() )
378 throw lang::IndexOutOfBoundsException("AccessibleEditableTextPara: character index out of bounds",
379 uno::Reference< uno::XInterface >
380 ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy
383 void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex )
385 if( nIndex < 0 || nIndex > getCharacterCount() )
386 throw lang::IndexOutOfBoundsException("AccessibleEditableTextPara: character position out of bounds",
387 uno::Reference< uno::XInterface >
388 ( static_cast< ::cppu::OWeakObject* > (this) ) ); // disambiguate hierarchy
391 void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd )
393 CheckPosition( nStart );
394 CheckPosition( nEnd );
397 bool AccessibleEditableTextPara::GetSelection(sal_Int32 &nStartPos, sal_Int32 &nEndPos)
399 ESelection aSelection;
400 sal_Int32 nPara = GetParagraphIndex();
401 if( !GetEditViewForwarder().GetSelection( aSelection ) )
402 return false;
404 if( aSelection.nStartPara < aSelection.nEndPara )
406 if( aSelection.nStartPara > nPara ||
407 aSelection.nEndPara < nPara )
408 return false;
410 if( nPara == aSelection.nStartPara )
411 nStartPos = aSelection.nStartPos;
412 else
413 nStartPos = 0;
415 if( nPara == aSelection.nEndPara )
416 nEndPos = aSelection.nEndPos;
417 else
418 nEndPos = GetTextLen();
420 else
422 if( aSelection.nStartPara < nPara ||
423 aSelection.nEndPara > nPara )
424 return false;
426 if( nPara == aSelection.nStartPara )
427 nStartPos = aSelection.nStartPos;
428 else
429 nStartPos = GetTextLen();
431 if( nPara == aSelection.nEndPara )
432 nEndPos = aSelection.nEndPos;
433 else
434 nEndPos = 0;
437 return true;
440 OUString AccessibleEditableTextPara::GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex )
442 return GetTextForwarder().GetText( MakeSelection(nStartIndex, nEndIndex) );
445 sal_Int32 AccessibleEditableTextPara::GetTextLen() const
447 return GetTextForwarder().GetTextLen(GetParagraphIndex());
450 SvxEditSourceAdapter& AccessibleEditableTextPara::GetEditSource() const
452 if( mpEditSource )
453 return *mpEditSource;
454 else
455 throw uno::RuntimeException("No edit source, object is defunct",
456 uno::Reference< uno::XInterface >
457 ( static_cast< ::cppu::OWeakObject* >
458 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
461 SvxAccessibleTextAdapter& AccessibleEditableTextPara::GetTextForwarder() const
463 SvxEditSourceAdapter& rEditSource = GetEditSource();
464 SvxAccessibleTextAdapter* pTextForwarder = rEditSource.GetTextForwarderAdapter();
466 if( !pTextForwarder )
467 throw uno::RuntimeException("Unable to fetch text forwarder, object is defunct",
468 uno::Reference< uno::XInterface >
469 ( static_cast< ::cppu::OWeakObject* >
470 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
472 if( pTextForwarder->IsValid() )
473 return *pTextForwarder;
474 else
475 throw uno::RuntimeException("Text forwarder is invalid, object is defunct",
476 uno::Reference< uno::XInterface >
477 ( static_cast< ::cppu::OWeakObject* >
478 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
481 SvxViewForwarder& AccessibleEditableTextPara::GetViewForwarder() const
483 SvxEditSource& rEditSource = GetEditSource();
484 SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder();
486 if( !pViewForwarder )
488 throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct",
489 uno::Reference< uno::XInterface >
490 ( static_cast< ::cppu::OWeakObject* >
491 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
494 if( pViewForwarder->IsValid() )
495 return *pViewForwarder;
496 else
497 throw uno::RuntimeException("View forwarder is invalid, object is defunct",
498 uno::Reference< uno::XInterface >
499 ( static_cast< ::cppu::OWeakObject* >
500 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
503 SvxAccessibleTextEditViewAdapter& AccessibleEditableTextPara::GetEditViewForwarder( bool bCreate ) const
505 SvxEditSourceAdapter& rEditSource = GetEditSource();
506 SvxAccessibleTextEditViewAdapter* pTextEditViewForwarder = rEditSource.GetEditViewForwarderAdapter( bCreate );
508 if( !pTextEditViewForwarder )
510 if( bCreate )
511 throw uno::RuntimeException("Unable to fetch view forwarder, object is defunct",
512 uno::Reference< uno::XInterface >
513 ( static_cast< ::cppu::OWeakObject* >
514 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
515 else
516 throw uno::RuntimeException("No view forwarder, object not in edit mode",
517 uno::Reference< uno::XInterface >
518 ( static_cast< ::cppu::OWeakObject* >
519 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
522 if( pTextEditViewForwarder->IsValid() )
523 return *pTextEditViewForwarder;
524 else
526 if( bCreate )
527 throw uno::RuntimeException("View forwarder is invalid, object is defunct",
528 uno::Reference< uno::XInterface >
529 ( static_cast< ::cppu::OWeakObject* >
530 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
531 else
532 throw uno::RuntimeException("View forwarder is invalid, object not in edit mode",
533 uno::Reference< uno::XInterface >
534 ( static_cast< ::cppu::OWeakObject* >
535 ( const_cast< AccessibleEditableTextPara* > (this) ) ) ); // disambiguate hierarchy
539 bool AccessibleEditableTextPara::HaveEditView() const
541 SvxEditSource& rEditSource = GetEditSource();
542 SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder();
544 if( !pViewForwarder )
545 return false;
547 if( !pViewForwarder->IsValid() )
548 return false;
550 return true;
553 bool AccessibleEditableTextPara::HaveChildren()
555 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
556 "AccessibleEditableTextPara::HaveChildren: paragraph index value overflow");
558 return GetTextForwarder().HaveImageBullet( GetParagraphIndex() );
561 Rectangle AccessibleEditableTextPara::LogicToPixel( const Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder& rForwarder )
563 // convert to screen coordinates
564 return Rectangle( rForwarder.LogicToPixel( rRect.TopLeft(), rMapMode ),
565 rForwarder.LogicToPixel( rRect.BottomRight(), rMapMode ) );
569 void AccessibleEditableTextPara::SetEEOffset( const Point& rOffset )
571 WeakBullet::HardRefType aChild( maImageBullet.get() );
572 if( aChild.is() )
573 aChild->SetEEOffset(rOffset);
575 maEEOffset = rOffset;
578 void AccessibleEditableTextPara::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue) const
580 uno::Reference < XAccessibleContext > xThis( const_cast< AccessibleEditableTextPara* > (this)->getAccessibleContext() );
582 AccessibleEventObject aEvent(xThis, nEventId, rNewValue, rOldValue);
584 // #102261# Call global queue for focus events
585 if( nEventId == AccessibleEventId::STATE_CHANGED )
586 vcl::unohelper::NotifyAccessibleStateEventGlobally( aEvent );
588 // #106234# Delegate to EventNotifier
589 if( getNotifierClientId() != -1 )
590 ::comphelper::AccessibleEventNotifier::addEvent( getNotifierClientId(),
591 aEvent );
594 void AccessibleEditableTextPara::GotPropertyEvent( const uno::Any& rNewValue, const sal_Int16 nEventId ) const
596 FireEvent( nEventId, rNewValue );
599 void AccessibleEditableTextPara::LostPropertyEvent( const uno::Any& rOldValue, const sal_Int16 nEventId ) const
601 FireEvent( nEventId, uno::Any(), rOldValue );
604 void AccessibleEditableTextPara::SetState( const sal_Int16 nStateId )
606 ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
607 if( pStateSet != NULL &&
608 !pStateSet->contains(nStateId) )
610 pStateSet->AddState( nStateId );
611 GotPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED );
615 void AccessibleEditableTextPara::UnSetState( const sal_Int16 nStateId )
617 ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
618 if( pStateSet != NULL &&
619 pStateSet->contains(nStateId) )
621 pStateSet->RemoveState( nStateId );
622 LostPropertyEvent( uno::makeAny( nStateId ), AccessibleEventId::STATE_CHANGED );
626 void AccessibleEditableTextPara::TextChanged()
628 OUString aCurrentString( OCommonAccessibleText::getText() );
629 uno::Any aDeleted;
630 uno::Any aInserted;
631 if( OCommonAccessibleText::implInitTextChangedEvent( maLastTextString, aCurrentString,
632 aDeleted, aInserted) )
634 FireEvent( AccessibleEventId::TEXT_CHANGED, aInserted, aDeleted );
635 maLastTextString = aCurrentString;
639 bool AccessibleEditableTextPara::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nIndex )
641 DBG_ASSERT(nIndex >= 0 && nIndex <= SAL_MAX_INT32,
642 "AccessibleEditableTextPara::GetAttributeRun: index value overflow");
644 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
645 "AccessibleEditableTextPara::getLocale: paragraph index value overflow");
647 return GetTextForwarder().GetAttributeRun( nStartIndex,
648 nEndIndex,
649 GetParagraphIndex(),
650 nIndex );
653 uno::Any SAL_CALL AccessibleEditableTextPara::queryInterface (const uno::Type & rType) throw (uno::RuntimeException, std::exception)
655 uno::Any aRet;
657 // must provide XAccesibleText by hand, since it comes publicly inherited by XAccessibleEditableText
658 if ( rType == cppu::UnoType<XAccessibleText>::get())
660 uno::Reference< XAccessibleText > aAccText = static_cast< XAccessibleEditableText * >(this);
661 aRet <<= aAccText;
663 else if ( rType == cppu::UnoType<XAccessibleEditableText>::get())
665 uno::Reference< XAccessibleEditableText > aAccEditText = this;
666 aRet <<= aAccEditText;
668 else if ( rType == cppu::UnoType<XAccessibleHypertext>::get())
670 uno::Reference< XAccessibleHypertext > aAccHyperText = this;
671 aRet <<= aAccHyperText;
673 else
675 aRet = AccessibleTextParaInterfaceBase::queryInterface(rType);
678 return aRet;
681 // XAccessible
682 uno::Reference< XAccessibleContext > SAL_CALL AccessibleEditableTextPara::getAccessibleContext() throw (uno::RuntimeException, std::exception)
684 // We implement the XAccessibleContext interface in the same object
685 return uno::Reference< XAccessibleContext > ( this );
688 // XAccessibleContext
689 sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() throw (uno::RuntimeException, std::exception)
691 SolarMutexGuard aGuard;
693 return HaveChildren() ? 1 : 0;
696 uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int32 i ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
698 SolarMutexGuard aGuard;
700 if( !HaveChildren() )
701 throw lang::IndexOutOfBoundsException("No children available",
702 uno::Reference< uno::XInterface >
703 ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy
705 if( i != 0 )
706 throw lang::IndexOutOfBoundsException("Invalid child index",
707 uno::Reference< uno::XInterface >
708 ( static_cast< ::cppu::OWeakObject* > (this) ) ); // static_cast: disambiguate hierarchy
710 WeakBullet::HardRefType aChild( maImageBullet.get() );
712 if( !aChild.is() )
714 // there is no hard reference available, create object then
715 AccessibleImageBullet* pChild = new AccessibleImageBullet( uno::Reference< XAccessible >( this ) );
716 uno::Reference< XAccessible > xChild( static_cast< ::cppu::OWeakObject* > (pChild), uno::UNO_QUERY );
718 if( !xChild.is() )
719 throw uno::RuntimeException("Child creation failed",
720 uno::Reference< uno::XInterface >
721 ( static_cast< ::cppu::OWeakObject* > (this) ) );
723 aChild = WeakBullet::HardRefType( xChild, pChild );
725 aChild->SetEditSource( &GetEditSource() );
726 aChild->SetParagraphIndex( GetParagraphIndex() );
727 aChild->SetIndexInParent( i );
729 maImageBullet = aChild;
732 return aChild.getRef();
735 uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent() throw (uno::RuntimeException, std::exception)
738 #ifdef DBG_UTIL
739 if( !mxParent.is() )
740 OSL_TRACE( "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?");
741 #endif
743 return mxParent;
746 sal_Int32 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() throw (uno::RuntimeException, std::exception)
748 return mnIndexInParent;
751 sal_Int16 SAL_CALL AccessibleEditableTextPara::getAccessibleRole() throw (uno::RuntimeException, std::exception)
753 return AccessibleRole::PARAGRAPH;
756 OUString SAL_CALL AccessibleEditableTextPara::getAccessibleDescription() throw (uno::RuntimeException, std::exception)
758 SolarMutexGuard aGuard;
760 // append first 40 characters from text, or first line, if shorter
761 // (writer takes first sentence here, but that's not supported
762 // from EditEngine)
763 // throws if defunc
764 OUString aLine;
766 if( getCharacterCount() )
767 aLine = getTextAtIndex(0, AccessibleTextType::LINE).SegmentText;
769 // Get the string from the resource for the specified id.
770 OUString sStr(EditResId(RID_SVXSTR_A11Y_PARAGRAPH_DESCRIPTION));
771 OUString sParaIndex = OUString::number(GetParagraphIndex());
772 sStr = sStr.replaceFirst("$(ARG)", sParaIndex);
774 if( aLine.getLength() > MaxDescriptionLen )
776 OUString aCurrWord;
777 sal_Int32 i;
779 // search backward from MaxDescriptionLen for previous word start
780 for( aCurrWord=getTextAtIndex(MaxDescriptionLen, AccessibleTextType::WORD).SegmentText,
781 i=MaxDescriptionLen,
782 aLine=OUString();
783 i>=0;
784 --i )
786 if( getTextAtIndex(i, AccessibleTextType::WORD).SegmentText != aCurrWord )
788 if( i == 0 )
789 // prevent completely empty string
790 aLine = getTextAtIndex(0, AccessibleTextType::WORD).SegmentText;
791 else
792 aLine = getTextRange(0, i);
797 return OUString( sStr ) + aLine;
800 OUString SAL_CALL AccessibleEditableTextPara::getAccessibleName() throw (uno::RuntimeException, std::exception)
802 SolarMutexGuard aGuard;
804 // throws if defunc
805 sal_Int32 nPara( GetParagraphIndex() );
807 // Get the string from the resource for the specified id.
808 OUString sStr(EditResId(RID_SVXSTR_A11Y_PARAGRAPH_NAME));
809 OUString sParaIndex = OUString::number(nPara);
810 return sStr.replaceFirst("$(ARG)", sParaIndex);
813 uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleEditableTextPara::getAccessibleRelationSet() throw (uno::RuntimeException, std::exception)
815 // #i27138# - provide relations CONTENT_FLOWS_FROM
816 // and CONTENT_FLOWS_TO
817 if ( mpParaManager )
819 utl::AccessibleRelationSetHelper* pAccRelSetHelper =
820 new utl::AccessibleRelationSetHelper();
821 sal_Int32 nMyParaIndex( GetParagraphIndex() );
822 // relation CONTENT_FLOWS_FROM
823 if ( nMyParaIndex > 0 &&
824 mpParaManager->IsReferencable( nMyParaIndex - 1 ) )
826 uno::Sequence<uno::Reference<XInterface> > aSequence(1);
827 aSequence[0] =
828 mpParaManager->GetChild( nMyParaIndex - 1 ).first.get().getRef();
829 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_FROM,
830 aSequence );
831 pAccRelSetHelper->AddRelation( aAccRel );
834 // relation CONTENT_FLOWS_TO
835 if ( (nMyParaIndex + 1) < (sal_Int32)mpParaManager->GetNum() &&
836 mpParaManager->IsReferencable( nMyParaIndex + 1 ) )
838 uno::Sequence<uno::Reference<XInterface> > aSequence(1);
839 aSequence[0] =
840 mpParaManager->GetChild( nMyParaIndex + 1 ).first.get().getRef();
841 AccessibleRelation aAccRel( AccessibleRelationType::CONTENT_FLOWS_TO,
842 aSequence );
843 pAccRelSetHelper->AddRelation( aAccRel );
846 return pAccRelSetHelper;
848 else
850 // no relations, therefore empty
851 return uno::Reference< XAccessibleRelationSet >();
855 static uno::Sequence< OUString > getAttributeNames()
857 static uno::Sequence< OUString >* pNames = NULL;
859 if( pNames == NULL )
861 uno::Sequence< OUString >* pSeq = new uno::Sequence< OUString >( 21 );
862 OUString* pStrings = pSeq->getArray();
863 sal_Int32 i = 0;
864 #define STR(x) pStrings[i++] = x
865 STR("CharColor");
866 STR("CharContoured");
867 STR("CharEmphasis");
868 STR("CharEscapement");
869 STR("CharFontName");
870 STR("CharHeight");
871 STR("CharPosture");
872 STR("CharShadowed");
873 STR("CharStrikeout");
874 STR("CharCaseMap");
875 STR("CharUnderline");
876 STR("CharUnderlineColor");
877 STR("CharWeight");
878 STR("NumberingLevel");
879 STR("NumberingRules");
880 STR("ParaAdjust");
881 STR("ParaBottomMargin");
882 STR("ParaFirstLineIndent");
883 STR("ParaLeftMargin");
884 STR("ParaLineSpacing");
885 STR("ParaRightMargin");
886 STR("ParaTabStops");
887 #undef STR
888 DBG_ASSERT( i == pSeq->getLength(), "Please adjust length" );
889 if( i != pSeq->getLength() )
890 pSeq->realloc( i );
891 pNames = pSeq;
893 return *pNames;
896 struct IndexCompare
898 const PropertyValue* pValues;
899 IndexCompare( const PropertyValue* pVals ) : pValues(pVals) {}
900 bool operator() ( const sal_Int32& a, const sal_Int32& b ) const
902 return pValues[a].Name < pValues[b].Name;
906 OUString AccessibleEditableTextPara::GetFieldTypeNameAtIndex(sal_Int32 nIndex)
908 OUString strFldType;
909 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
910 //For field object info
911 sal_Int32 nParaIndex = GetParagraphIndex();
912 sal_Int32 nAllFieldLen = 0;
913 sal_Int32 nField = rCacheTF.GetFieldCount(nParaIndex), nFoundFieldIndex = -1;
914 EFieldInfo ree;
915 sal_Int32 reeBegin, reeEnd;
916 sal_Int32 nFieldType = -1;
917 for(sal_Int32 j = 0; j < nField; j++)
919 ree = rCacheTF.GetFieldInfo(nParaIndex, j);
920 reeBegin = ree.aPosition.nIndex + nAllFieldLen;
921 reeEnd = reeBegin + ree.aCurrentText.getLength();
922 nAllFieldLen += (ree.aCurrentText.getLength() - 1);
923 if( reeBegin > nIndex )
925 break;
927 if( nIndex >= reeBegin && nIndex < reeEnd )
929 nFoundFieldIndex = j;
930 break;
933 if (nFoundFieldIndex >= 0 && ree.pFieldItem)
935 // So we get a field, check its type now.
936 nFieldType = ree.pFieldItem->GetField()->GetClassId() ;
938 switch(nFieldType)
940 case text::textfield::Type::DATE:
942 const SvxDateField* pDateField = static_cast< const SvxDateField* >(ree.pFieldItem->GetField());
943 if (pDateField)
945 if (pDateField->GetType() == SVXDATETYPE_FIX)
946 strFldType = "date (fixed)";
947 else if (pDateField->GetType() == SVXDATETYPE_VAR)
948 strFldType = "date (variable)";
951 break;
952 case text::textfield::Type::PAGE:
953 strFldType = "page-number";
954 break;
955 //support the sheet name & pages fields
956 case text::textfield::Type::PAGES:
957 strFldType = "page-count";
958 break;
959 case text::textfield::Type::TABLE:
960 strFldType = "sheet-name";
961 break;
962 //End
963 case text::textfield::Type::TIME:
964 strFldType = "time";
965 break;
966 case text::textfield::Type::EXTENDED_TIME:
968 const SvxExtTimeField* pTimeField = static_cast< const SvxExtTimeField* >(ree.pFieldItem->GetField());
969 if (pTimeField)
971 if (pTimeField->GetType() == SVXTIMETYPE_FIX)
972 strFldType = "time (fixed)";
973 else if (pTimeField->GetType() == SVXTIMETYPE_VAR)
974 strFldType = "time (variable)";
977 break;
978 case text::textfield::Type::AUTHOR:
979 strFldType = "author";
980 break;
981 case text::textfield::Type::EXTENDED_FILE:
982 case text::textfield::Type::DOCINFO_TITLE:
983 strFldType = "file name";
984 default:
985 break;
987 return strFldType;
990 uno::Reference< XAccessibleStateSet > SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() throw (uno::RuntimeException, std::exception)
992 SolarMutexGuard aGuard;
994 // Create a copy of the state set and return it.
995 ::utl::AccessibleStateSetHelper* pStateSet = static_cast< ::utl::AccessibleStateSetHelper*>(mxStateSet.get());
997 if( !pStateSet )
998 return uno::Reference<XAccessibleStateSet>();
999 uno::Reference<XAccessibleStateSet> xParentStates;
1000 if (getAccessibleParent().is())
1002 uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext();
1003 xParentStates = xParentContext->getAccessibleStateSet();
1005 if (xParentStates.is() && xParentStates->contains(AccessibleStateType::EDITABLE) )
1007 pStateSet->AddState(AccessibleStateType::EDITABLE);
1009 return uno::Reference<XAccessibleStateSet>( new ::utl::AccessibleStateSetHelper (*pStateSet) );
1012 lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale() throw (IllegalAccessibleComponentStateException, uno::RuntimeException, std::exception)
1014 SolarMutexGuard aGuard;
1016 return implGetLocale();
1019 void SAL_CALL AccessibleEditableTextPara::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException, std::exception)
1021 if( getNotifierClientId() != -1 )
1022 ::comphelper::AccessibleEventNotifier::addEventListener( getNotifierClientId(), xListener );
1025 void SAL_CALL AccessibleEditableTextPara::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener ) throw (uno::RuntimeException, std::exception)
1027 if( getNotifierClientId() != -1 )
1029 const sal_Int32 nListenerCount = ::comphelper::AccessibleEventNotifier::removeEventListener( getNotifierClientId(), xListener );
1030 if ( !nListenerCount )
1032 // no listeners anymore
1033 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
1034 // and at least to us not firing any events anymore, in case somebody calls
1035 // NotifyAccessibleEvent, again
1036 ::comphelper::AccessibleEventNotifier::TClientId nId( getNotifierClientId() );
1037 mnNotifierClientId = -1;
1038 ::comphelper::AccessibleEventNotifier::revokeClient( nId );
1043 // XAccessibleComponent
1044 sal_Bool SAL_CALL AccessibleEditableTextPara::containsPoint( const awt::Point& aTmpPoint ) throw (uno::RuntimeException, std::exception)
1046 SolarMutexGuard aGuard;
1048 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
1049 "AccessibleEditableTextPara::contains: index value overflow");
1051 awt::Rectangle aTmpRect = getBounds();
1052 Rectangle aRect( Point(aTmpRect.X, aTmpRect.Y), Size(aTmpRect.Width, aTmpRect.Height) );
1053 Point aPoint( aTmpPoint.X, aTmpPoint.Y );
1055 return aRect.IsInside( aPoint );
1058 uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint ) throw (uno::RuntimeException, std::exception)
1060 SolarMutexGuard aGuard;
1062 if( HaveChildren() )
1064 // #103862# No longer need to make given position relative
1065 Point aPoint( _aPoint.X, _aPoint.Y );
1067 // respect EditEngine offset to surrounding shape/cell
1068 aPoint -= GetEEOffset();
1070 // convert to EditEngine coordinate system
1071 SvxTextForwarder& rCacheTF = GetTextForwarder();
1072 Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1074 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
1076 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
1077 aBulletInfo.bVisible &&
1078 aBulletInfo.nType == SVX_NUM_BITMAP )
1080 Rectangle aRect = aBulletInfo.aBounds;
1082 if( aRect.IsInside( aLogPoint ) )
1083 return getAccessibleChild(0);
1087 // no children at all, or none at given position
1088 return uno::Reference< XAccessible >();
1091 awt::Rectangle SAL_CALL AccessibleEditableTextPara::getBounds() throw (uno::RuntimeException, std::exception)
1093 SolarMutexGuard aGuard;
1095 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= SAL_MAX_INT32,
1096 "AccessibleEditableTextPara::getBounds: index value overflow");
1098 SvxTextForwarder& rCacheTF = GetTextForwarder();
1099 Rectangle aRect = rCacheTF.GetParaBounds( GetParagraphIndex() );
1101 // convert to screen coordinates
1102 Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect,
1103 rCacheTF.GetMapMode(),
1104 GetViewForwarder() );
1106 // offset from shape/cell
1107 Point aOffset = GetEEOffset();
1109 return awt::Rectangle( aScreenRect.Left() + aOffset.X(),
1110 aScreenRect.Top() + aOffset.Y(),
1111 aScreenRect.GetSize().Width(),
1112 aScreenRect.GetSize().Height() );
1115 awt::Point SAL_CALL AccessibleEditableTextPara::getLocation( ) throw (uno::RuntimeException, std::exception)
1117 SolarMutexGuard aGuard;
1119 awt::Rectangle aRect = getBounds();
1121 return awt::Point( aRect.X, aRect.Y );
1124 awt::Point SAL_CALL AccessibleEditableTextPara::getLocationOnScreen( ) throw (uno::RuntimeException, std::exception)
1126 SolarMutexGuard aGuard;
1128 // relate us to parent
1129 uno::Reference< XAccessible > xParent = getAccessibleParent();
1130 if( xParent.is() )
1132 uno::Reference< XAccessibleComponent > xParentComponent( xParent, uno::UNO_QUERY );
1133 if( xParentComponent.is() )
1135 awt::Point aRefPoint = xParentComponent->getLocationOnScreen();
1136 awt::Point aPoint = getLocation();
1137 aPoint.X += aRefPoint.X;
1138 aPoint.Y += aRefPoint.Y;
1140 return aPoint;
1142 // #i88070#
1143 // fallback to parent's <XAccessibleContext> instance
1144 else
1146 uno::Reference< XAccessibleContext > xParentContext = xParent->getAccessibleContext();
1147 if ( xParentContext.is() )
1149 uno::Reference< XAccessibleComponent > xParentContextComponent( xParentContext, uno::UNO_QUERY );
1150 if( xParentContextComponent.is() )
1152 awt::Point aRefPoint = xParentContextComponent->getLocationOnScreen();
1153 awt::Point aPoint = getLocation();
1154 aPoint.X += aRefPoint.X;
1155 aPoint.Y += aRefPoint.Y;
1157 return aPoint;
1163 throw uno::RuntimeException("Cannot access parent",
1164 uno::Reference< uno::XInterface >
1165 ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
1168 awt::Size SAL_CALL AccessibleEditableTextPara::getSize( ) throw (uno::RuntimeException, std::exception)
1170 SolarMutexGuard aGuard;
1172 awt::Rectangle aRect = getBounds();
1174 return awt::Size( aRect.Width, aRect.Height );
1177 void SAL_CALL AccessibleEditableTextPara::grabFocus( ) throw (uno::RuntimeException, std::exception)
1179 // set cursor to this paragraph
1180 setSelection(0,0);
1183 sal_Int32 SAL_CALL AccessibleEditableTextPara::getForeground( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1185 // #104444# Added to XAccessibleComponent interface
1186 svtools::ColorConfig aColorConfig;
1187 sal_uInt32 nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor;
1188 return static_cast<sal_Int32>(nColor);
1191 sal_Int32 SAL_CALL AccessibleEditableTextPara::getBackground( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
1193 // #104444# Added to XAccessibleComponent interface
1194 Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor().GetColor() );
1196 // the background is transparent
1197 aColor.SetTransparency( 0xFF);
1199 return static_cast<sal_Int32>( aColor.GetColor() );
1202 // XAccessibleText
1203 sal_Int32 SAL_CALL AccessibleEditableTextPara::getCaretPosition() throw (uno::RuntimeException, std::exception)
1205 SolarMutexGuard aGuard;
1207 if( !HaveEditView() )
1208 return -1;
1210 ESelection aSelection;
1211 if( GetEditViewForwarder().GetSelection( aSelection ) &&
1212 GetParagraphIndex() == aSelection.nEndPara )
1214 // caret is always nEndPara,nEndPos
1215 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
1216 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND &&
1217 aBulletInfo.bVisible &&
1218 aBulletInfo.nType != SVX_NUM_BITMAP )
1220 sal_Int32 nBulletLen = aBulletInfo.aText.getLength();
1221 if( aSelection.nEndPos - nBulletLen >= 0 )
1222 return aSelection.nEndPos - nBulletLen;
1224 return aSelection.nEndPos;
1227 // not within this paragraph
1228 return -1;
1231 sal_Bool SAL_CALL AccessibleEditableTextPara::setCaretPosition( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1233 return setSelection(nIndex, nIndex);
1236 sal_Unicode SAL_CALL AccessibleEditableTextPara::getCharacter( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1238 SolarMutexGuard aGuard;
1240 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1241 "AccessibleEditableTextPara::getCharacter: index value overflow");
1243 return OCommonAccessibleText::getCharacter( nIndex );
1246 uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getCharacterAttributes( sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< OUString >& rRequestedAttributes ) throw (lang::IndexOutOfBoundsException, beans::UnknownPropertyException, uno::RuntimeException, std::exception)
1248 SolarMutexGuard aGuard;
1250 //Skip the bullet range to ingnore the bullet text
1251 SvxTextForwarder& rCacheTF = GetTextForwarder();
1252 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
1253 if (aBulletInfo.bVisible)
1254 nIndex += aBulletInfo.aText.getLength();
1255 CheckIndex(nIndex); // may throw IndexOutOfBoundsException
1257 bool bSupplementalMode = false;
1258 uno::Sequence< OUString > aPropertyNames = rRequestedAttributes;
1259 if (aPropertyNames.getLength() == 0)
1261 bSupplementalMode = true;
1262 aPropertyNames = getAttributeNames();
1265 // get default attribues...
1266 ::comphelper::SequenceAsHashMap aPropHashMap( getDefaultAttributes( aPropertyNames ) );
1268 // ... and override them with the direct attributes from the specific position
1269 uno::Sequence< beans::PropertyValue > aRunAttribs( getRunAttributes( nIndex, aPropertyNames ) );
1270 sal_Int32 nRunAttribs = aRunAttribs.getLength();
1271 const beans::PropertyValue *pRunAttrib = aRunAttribs.getConstArray();
1272 for (sal_Int32 k = 0; k < nRunAttribs; ++k)
1274 const beans::PropertyValue &rRunAttrib = pRunAttrib[k];
1275 aPropHashMap[ rRunAttrib.Name ] = rRunAttrib.Value; //!! should not only be the value !!
1278 // get resulting sequence
1279 uno::Sequence< beans::PropertyValue > aRes;
1280 aPropHashMap >> aRes;
1282 // since SequenceAsHashMap ignores property handles and property state
1283 // we have to restore the property state here (property handles are
1284 // of no use to the accessibility API).
1285 sal_Int32 nRes = aRes.getLength();
1286 beans::PropertyValue *pRes = aRes.getArray();
1287 for (sal_Int32 i = 0; i < nRes; ++i)
1289 beans::PropertyValue &rRes = pRes[i];
1290 bool bIsDirectVal = false;
1291 for (sal_Int32 k = 0; k < nRunAttribs && !bIsDirectVal; ++k)
1293 if (rRes.Name == pRunAttrib[k].Name)
1294 bIsDirectVal = true;
1296 rRes.Handle = -1;
1297 rRes.State = bIsDirectVal ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE;
1299 if( bSupplementalMode )
1301 _correctValues( nIndex, aRes );
1302 // NumberingPrefix
1303 nRes = aRes.getLength();
1304 aRes.realloc( nRes + 1 );
1305 pRes = aRes.getArray();
1306 beans::PropertyValue &rRes = pRes[nRes];
1307 rRes.Name = "NumberingPrefix";
1308 OUString numStr;
1309 if (aBulletInfo.nType != SVX_NUM_CHAR_SPECIAL && aBulletInfo.nType != SVX_NUM_BITMAP)
1310 numStr = aBulletInfo.aText;
1311 rRes.Value <<= numStr;
1312 rRes.Handle = -1;
1313 rRes.State = PropertyState_DIRECT_VALUE;
1314 //For field object.
1315 OUString strFieldType = GetFieldTypeNameAtIndex(nIndex);
1316 if (!strFieldType.isEmpty())
1318 nRes = aRes.getLength();
1319 aRes.realloc( nRes + 1 );
1320 pRes = aRes.getArray();
1321 beans::PropertyValue &rResField = pRes[nRes];
1322 beans::PropertyValue aFieldType;
1323 rResField.Name = "FieldType";
1324 rResField.Value <<= strFieldType.toAsciiLowerCase();
1325 rResField.Handle = -1;
1326 rResField.State = PropertyState_DIRECT_VALUE;
1328 //sort property values
1329 // build sorted index array
1330 sal_Int32 nLength = aRes.getLength();
1331 const beans::PropertyValue* pPairs = aRes.getConstArray();
1332 boost::scoped_array<sal_Int32> pIndices(new sal_Int32[nLength]);
1333 sal_Int32 i = 0;
1334 for( i = 0; i < nLength; i++ )
1335 pIndices[i] = i;
1336 sort( &pIndices[0], &pIndices[nLength], IndexCompare(pPairs) );
1337 // create sorted sequences according to index array
1338 uno::Sequence<beans::PropertyValue> aNewValues( nLength );
1339 beans::PropertyValue* pNewValues = aNewValues.getArray();
1340 for( i = 0; i < nLength; i++ )
1342 pNewValues[i] = pPairs[pIndices[i]];
1345 return aNewValues;
1347 return aRes;
1350 awt::Rectangle SAL_CALL AccessibleEditableTextPara::getCharacterBounds( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1352 SolarMutexGuard aGuard;
1354 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1355 "AccessibleEditableTextPara::getCharacterBounds: index value overflow");
1357 // #108900# Have position semantics now for nIndex, as
1358 // one-past-the-end values are legal, too.
1359 CheckPosition( nIndex );
1361 SvxTextForwarder& rCacheTF = GetTextForwarder();
1362 Rectangle aRect = rCacheTF.GetCharBounds(GetParagraphIndex(), nIndex);
1364 // convert to screen
1365 Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect,
1366 rCacheTF.GetMapMode(),
1367 GetViewForwarder() );
1368 // #109864# offset from parent (paragraph), but in screen
1369 // coordinates. This makes sure the internal text offset in
1370 // the outline view forwarder gets cancelled out here
1371 awt::Rectangle aParaRect( getBounds() );
1372 aScreenRect.Move( -aParaRect.X, -aParaRect.Y );
1374 // offset from shape/cell
1375 Point aOffset = GetEEOffset();
1377 return awt::Rectangle( aScreenRect.Left() + aOffset.X(),
1378 aScreenRect.Top() + aOffset.Y(),
1379 aScreenRect.GetSize().Width(),
1380 aScreenRect.GetSize().Height() );
1383 sal_Int32 SAL_CALL AccessibleEditableTextPara::getCharacterCount() throw (uno::RuntimeException, std::exception)
1385 SolarMutexGuard aGuard;
1387 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1388 "AccessibleEditableTextPara::getCharacterCount: index value overflow");
1390 return OCommonAccessibleText::getCharacterCount();
1393 sal_Int32 SAL_CALL AccessibleEditableTextPara::getIndexAtPoint( const awt::Point& rPoint ) throw (uno::RuntimeException, std::exception)
1395 SolarMutexGuard aGuard;
1397 sal_Int32 nPara;
1398 sal_Int32 nIndex;
1400 // offset from surrounding cell/shape
1401 Point aOffset( GetEEOffset() );
1402 Point aPoint( rPoint.X - aOffset.X(), rPoint.Y - aOffset.Y() );
1404 // convert to logical coordinates
1405 SvxTextForwarder& rCacheTF = GetTextForwarder();
1406 Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) );
1408 // re-offset to parent (paragraph)
1409 Rectangle aParaRect = rCacheTF.GetParaBounds( GetParagraphIndex() );
1410 aLogPoint.Move( aParaRect.Left(), aParaRect.Top() );
1412 if( rCacheTF.GetIndexAtPoint( aLogPoint, nPara, nIndex ) &&
1413 GetParagraphIndex() == nPara )
1415 // #102259# Double-check if we're _really_ on the given character
1418 awt::Rectangle aRect1( getCharacterBounds(nIndex) );
1419 Rectangle aRect2( aRect1.X, aRect1.Y,
1420 aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y );
1421 if( aRect2.IsInside( Point( rPoint.X, rPoint.Y ) ) )
1422 return nIndex;
1423 else
1424 return -1;
1426 catch (const lang::IndexOutOfBoundsException&)
1428 // #103927# Don't throw for invalid nIndex values
1429 return -1;
1432 else
1434 // not within our paragraph
1435 return -1;
1439 OUString SAL_CALL AccessibleEditableTextPara::getSelectedText() throw (uno::RuntimeException, std::exception)
1441 SolarMutexGuard aGuard;
1443 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1444 "AccessibleEditableTextPara::getSelectedText: index value overflow");
1446 if( !HaveEditView() )
1447 return OUString();
1449 return OCommonAccessibleText::getSelectedText();
1452 sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionStart() throw (uno::RuntimeException, std::exception)
1454 SolarMutexGuard aGuard;
1456 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1457 "AccessibleEditableTextPara::getSelectionStart: index value overflow");
1459 if( !HaveEditView() )
1460 return -1;
1462 return OCommonAccessibleText::getSelectionStart();
1465 sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionEnd() throw (uno::RuntimeException, std::exception)
1467 SolarMutexGuard aGuard;
1469 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1470 "AccessibleEditableTextPara::getSelectionEnd: index value overflow");
1472 if( !HaveEditView() )
1473 return -1;
1475 return OCommonAccessibleText::getSelectionEnd();
1478 sal_Bool SAL_CALL AccessibleEditableTextPara::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1480 SolarMutexGuard aGuard;
1482 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1483 "AccessibleEditableTextPara::setSelection: paragraph index value overflow");
1485 CheckRange(nStartIndex, nEndIndex);
1489 SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
1490 return rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
1492 catch (const uno::RuntimeException&)
1494 return sal_False;
1498 OUString SAL_CALL AccessibleEditableTextPara::getText() throw (uno::RuntimeException, std::exception)
1500 SolarMutexGuard aGuard;
1502 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1503 "AccessibleEditableTextPara::getText: paragraph index value overflow");
1505 return OCommonAccessibleText::getText();
1508 OUString SAL_CALL AccessibleEditableTextPara::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
1510 SolarMutexGuard aGuard;
1512 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1513 "AccessibleEditableTextPara::getTextRange: paragraph index value overflow");
1515 return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex);
1518 void AccessibleEditableTextPara::_correctValues( const sal_Int32 /* nIndex */,
1519 uno::Sequence< PropertyValue >& rValues)
1521 SvxTextForwarder& rCacheTF = GetTextForwarder();
1522 sal_Int32 nRes = rValues.getLength();
1523 beans::PropertyValue *pRes = rValues.getArray();
1524 for (sal_Int32 i = 0; i < nRes; ++i)
1526 beans::PropertyValue &rRes = pRes[i];
1527 // Char color
1528 if (rRes.Name == "CharColor")
1530 uno::Any &anyChar = rRes.Value;
1531 sal_uInt32 crChar = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>(anyChar.pReserved));
1532 if (COL_AUTO == crChar )
1534 uno::Reference< ::com::sun::star::accessibility::XAccessibleComponent > xComponent;
1535 if (mxParent.is())
1537 xComponent.set(mxParent,uno::UNO_QUERY);
1539 else
1541 xComponent.set(m_xAccInfo,uno::UNO_QUERY);
1543 if (xComponent.is())
1545 uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xContext(xComponent,uno::UNO_QUERY);
1546 if (xContext->getAccessibleRole() == AccessibleRole::SHAPE
1547 || xContext->getAccessibleRole() == AccessibleRole::TABLE_CELL)
1549 anyChar <<= COL_BLACK;
1551 else
1553 Color cr(xComponent->getBackground());
1554 crChar = cr.IsDark() ? COL_WHITE : COL_BLACK;
1555 anyChar <<= crChar;
1559 continue;
1561 // Underline
1562 if (rRes.Name == "CharUnderline")
1564 continue;
1566 // Underline color && Mis-spell
1567 if (rRes.Name == "CharUnderlineColor")
1569 uno::Any &anyCharUnderLine = rRes.Value;
1570 sal_uInt32 crCharUnderLine = static_cast<sal_uInt32>( reinterpret_cast<sal_uIntPtr>( anyCharUnderLine.pReserved));
1571 if (COL_AUTO == crCharUnderLine )
1573 uno::Reference< ::com::sun::star::accessibility::XAccessibleComponent > xComponent;
1574 if (mxParent.is())
1576 xComponent.set(mxParent,uno::UNO_QUERY);
1578 else
1580 xComponent.set(m_xAccInfo,uno::UNO_QUERY);
1582 if (xComponent.is())
1584 uno::Reference< ::com::sun::star::accessibility::XAccessibleContext > xContext(xComponent,uno::UNO_QUERY);
1585 if (xContext->getAccessibleRole() == AccessibleRole::SHAPE
1586 || xContext->getAccessibleRole() == AccessibleRole::TABLE_CELL)
1588 anyCharUnderLine <<= COL_BLACK;
1590 else
1592 Color cr(xComponent->getBackground());
1593 crCharUnderLine = cr.IsDark() ? COL_WHITE : COL_BLACK;
1594 anyCharUnderLine <<= crCharUnderLine;
1598 continue;
1600 // NumberingLevel
1601 if (rRes.Name == "NumberingLevel")
1603 const SvxNumBulletItem& rNumBullet = static_cast<const SvxNumBulletItem&>(rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET));
1604 if(rNumBullet.GetNumRule()->GetLevelCount()==0)
1606 rRes.Value <<= (sal_Int16)-1;
1607 rRes.Handle = -1;
1608 rRes.State = PropertyState_DIRECT_VALUE;
1610 else
1612 // SvxAccessibleTextPropertySet aPropSet( &GetEditSource(),
1613 // ImplGetSvxCharAndParaPropertiesMap() );
1614 // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap
1615 SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() );
1617 aPropSet.SetSelection( MakeSelection( 0, GetTextLen() ) );
1618 rRes.Value = aPropSet._getPropertyValue( rRes.Name, mnParagraphIndex );
1619 rRes.State = aPropSet._getPropertyState( rRes.Name, mnParagraphIndex );
1620 rRes.Handle = -1;
1622 continue;
1624 // NumberingRules
1625 if (rRes.Name == "NumberingRules")
1627 SfxItemSet aAttribs = rCacheTF.GetParaAttribs(GetParagraphIndex());
1628 bool bVis = static_cast<const SfxUInt16Item&>(aAttribs.Get( EE_PARA_BULLETSTATE )).GetValue() != 0;
1629 if(bVis)
1631 rRes.Value <<= (sal_Int16)-1;
1632 rRes.Handle = -1;
1633 rRes.State = PropertyState_DIRECT_VALUE;
1635 else
1637 // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap
1638 SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() );
1639 aPropSet.SetSelection( MakeSelection( 0, GetTextLen() ) );
1640 rRes.Value = aPropSet._getPropertyValue( rRes.Name, mnParagraphIndex );
1641 rRes.State = aPropSet._getPropertyState( rRes.Name, mnParagraphIndex );
1642 rRes.Handle = -1;
1644 continue;
1648 sal_Int32 AccessibleEditableTextPara::SkipField(sal_Int32 nIndex, bool bForward)
1650 sal_Int32 nParaIndex = GetParagraphIndex();
1651 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
1652 sal_Int32 nAllFieldLen = 0;
1653 sal_Int32 nField = rCacheTF.GetFieldCount(nParaIndex), nFoundFieldIndex = -1;
1654 EFieldInfo ree;
1655 sal_Int32 reeBegin=0, reeEnd=0;
1656 for (sal_Int32 j = 0; j < nField; j++)
1658 ree = rCacheTF.GetFieldInfo(nParaIndex, j);
1659 reeBegin = ree.aPosition.nIndex + nAllFieldLen;
1660 reeEnd = reeBegin + ree.aCurrentText.getLength();
1661 nAllFieldLen += (ree.aCurrentText.getLength() - 1);
1662 if( reeBegin > nIndex )
1664 break;
1666 if (!ree.pFieldItem)
1667 continue;
1668 if (nIndex >= reeBegin && nIndex < reeEnd)
1670 if (ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL)
1672 nFoundFieldIndex = j;
1673 break;
1677 if( nFoundFieldIndex >= 0 )
1679 if( bForward )
1680 return reeEnd - 1;
1681 else
1682 return reeBegin;
1684 return nIndex;
1686 bool AccessibleEditableTextPara::ExtendByField( ::com::sun::star::accessibility::TextSegment& Segment )
1688 sal_Int32 nParaIndex = GetParagraphIndex();
1689 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder();
1690 sal_Int32 nAllFieldLen = 0;
1691 sal_Int32 nField = rCacheTF.GetFieldCount(nParaIndex), nFoundFieldIndex = -1;
1692 EFieldInfo ree;
1693 sal_Int32 reeBegin=0, reeEnd=0;
1694 for (sal_Int32 j = 0; j < nField; j++)
1696 ree = rCacheTF.GetFieldInfo(nParaIndex, j);
1697 reeBegin = ree.aPosition.nIndex + nAllFieldLen;
1698 reeEnd = reeBegin + ree.aCurrentText.getLength();
1699 nAllFieldLen += (ree.aCurrentText.getLength() - 1);
1700 if( reeBegin > Segment.SegmentEnd )
1702 break;
1704 if (!ree.pFieldItem)
1705 continue;
1706 if( (Segment.SegmentEnd > reeBegin && Segment.SegmentEnd <= reeEnd) ||
1707 (Segment.SegmentStart >= reeBegin && Segment.SegmentStart < reeEnd) )
1709 if(ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL)
1711 nFoundFieldIndex = j;
1712 break;
1716 bool bExtend = false;
1717 if( nFoundFieldIndex >= 0 )
1719 if( Segment.SegmentEnd < reeEnd )
1721 Segment.SegmentEnd = reeEnd;
1722 bExtend = true;
1724 if( Segment.SegmentStart > reeBegin )
1726 Segment.SegmentStart = reeBegin;
1727 bExtend = true;
1729 if( bExtend )
1731 //If there is a bullet before the field, should add the bullet length into the segment.
1732 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
1733 sal_Int32 nBulletLen = aBulletInfo.aText.getLength();
1734 if (nBulletLen > 0)
1736 Segment.SegmentEnd += nBulletLen;
1737 if (nFoundFieldIndex > 0)
1738 Segment.SegmentStart += nBulletLen;
1739 Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd);
1740 //After get the correct field name, should restore the offset value which don't contain the bullet.
1741 Segment.SegmentEnd -= nBulletLen;
1742 if (nFoundFieldIndex > 0)
1743 Segment.SegmentStart -= nBulletLen;
1745 else
1746 Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd);
1749 return bExtend;
1752 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
1754 SolarMutexGuard aGuard;
1756 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1757 "AccessibleEditableTextPara::getTextAtIndex: paragraph index value overflow");
1759 ::com::sun::star::accessibility::TextSegment aResult;
1760 aResult.SegmentStart = -1;
1761 aResult.SegmentEnd = -1;
1763 switch( aTextType )
1765 case AccessibleTextType::CHARACTER:
1766 case AccessibleTextType::WORD:
1768 aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
1769 ExtendByField( aResult );
1770 break;
1772 // Not yet handled by OCommonAccessibleText. Missing
1773 // implGetAttributeRunBoundary() method there
1774 case AccessibleTextType::ATTRIBUTE_RUN:
1776 const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() );
1778 if( nIndex == nTextLen )
1780 // #i17014# Special-casing one-behind-the-end character
1781 aResult.SegmentStart = aResult.SegmentEnd = nTextLen;
1783 else
1785 sal_Int32 nStartIndex, nEndIndex;
1786 //For the bullet paragraph, the bullet string is ingnored for IAText::attributes() function.
1787 SvxTextForwarder& rCacheTF = GetTextForwarder();
1788 // MT IA2: Not used? sal_Int32 nBulletLen = 0;
1789 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex());
1790 if (aBulletInfo.bVisible)
1791 nIndex += aBulletInfo.aText.getLength();
1792 if (nIndex != 0 && nIndex >= getCharacterCount())
1793 nIndex = getCharacterCount()-1;
1794 CheckPosition(nIndex);
1795 if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
1797 aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1798 if (aBulletInfo.bVisible)
1800 nStartIndex -= aBulletInfo.aText.getLength();
1801 nEndIndex -= aBulletInfo.aText.getLength();
1803 aResult.SegmentStart = nStartIndex;
1804 aResult.SegmentEnd = nEndIndex;
1807 break;
1809 case AccessibleTextType::LINE:
1811 SvxTextForwarder& rCacheTF = GetTextForwarder();
1812 sal_Int32 nParaIndex = GetParagraphIndex();
1813 CheckPosition(nIndex);
1814 if (nIndex != 0 && nIndex == getCharacterCount())
1815 --nIndex;
1816 sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex );
1817 sal_Int32 nCurIndex;
1818 //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
1819 //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
1820 //by the IAText::attributes(). So here must do special support for bullet line.
1821 sal_Int32 nBulletLen = 0;
1822 for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
1824 if (nLine == 0)
1826 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( nParaIndex );
1827 if (aBulletInfo.bVisible)
1829 //in bullet or numbering;
1830 nBulletLen = aBulletInfo.aText.getLength();
1833 sal_Int32 nLineLen = rCacheTF.GetLineLen(nParaIndex, nLine);
1834 if (nLine == 0)
1835 nCurIndex += nLineLen - nBulletLen;
1836 else
1837 nCurIndex += nLineLen;
1838 if( nCurIndex > nIndex )
1840 if (nLine ==0)
1842 aResult.SegmentStart = 0;
1843 aResult.SegmentEnd = nCurIndex;
1844 aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen);
1845 break;
1847 else
1849 aResult.SegmentStart = nCurIndex - nLineLen;
1850 aResult.SegmentEnd = nCurIndex;
1851 //aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd );
1852 aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
1853 break;
1857 break;
1859 default:
1860 aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
1861 break;
1862 } /* end of switch( aTextType ) */
1864 return aResult;
1867 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
1869 SolarMutexGuard aGuard;
1871 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
1872 "AccessibleEditableTextPara::getTextBeforeIndex: paragraph index value overflow");
1874 ::com::sun::star::accessibility::TextSegment aResult;
1875 aResult.SegmentStart = -1;
1876 aResult.SegmentEnd = -1;
1877 i18n::Boundary aBoundary;
1878 switch( aTextType )
1880 // Not yet handled by OCommonAccessibleText. Missing
1881 // implGetAttributeRunBoundary() method there
1882 case AccessibleTextType::ATTRIBUTE_RUN:
1884 const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() );
1885 sal_Int32 nStartIndex, nEndIndex;
1887 if( nIndex == nTextLen )
1889 // #i17014# Special-casing one-behind-the-end character
1890 if( nIndex > 0 &&
1891 GetAttributeRun(nStartIndex, nEndIndex, nIndex-1) )
1893 aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1894 aResult.SegmentStart = nStartIndex;
1895 aResult.SegmentEnd = nEndIndex;
1898 else
1900 if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
1902 // already at the left border? If not, query
1903 // one index further left
1904 if( nStartIndex > 0 &&
1905 GetAttributeRun(nStartIndex, nEndIndex, nStartIndex-1) )
1907 aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
1908 aResult.SegmentStart = nStartIndex;
1909 aResult.SegmentEnd = nEndIndex;
1913 break;
1915 case AccessibleTextType::LINE:
1917 SvxTextForwarder& rCacheTF = GetTextForwarder();
1918 sal_Int32 nParaIndex = GetParagraphIndex();
1920 CheckPosition(nIndex);
1922 sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex );
1923 //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
1924 //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
1925 //by the IAText::attributes(). So here must do special support for bullet line.
1926 sal_Int32 nCurIndex=0, nLastIndex=0, nCurLineLen=0;
1927 sal_Int32 nLastLineLen = 0, nBulletLen = 0;;
1928 // get the line before the line the index points into
1929 for( nLine=0, nCurIndex=0, nLastIndex=0; nLine<nLineCount; ++nLine )
1931 nLastIndex = nCurIndex;
1932 if (nLine == 0)
1934 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
1935 if (aBulletInfo.bVisible)
1937 //in bullet or numbering;
1938 nBulletLen = aBulletInfo.aText.getLength();
1941 if (nLine == 1)
1942 nLastLineLen = nCurLineLen - nBulletLen;
1943 else
1944 nLastLineLen = nCurLineLen;
1945 nCurLineLen = rCacheTF.GetLineLen( nParaIndex, nLine);
1946 //nCurIndex += nCurLineLen;
1947 if (nLine == 0)
1948 nCurIndex += nCurLineLen - nBulletLen;
1949 else
1950 nCurIndex += nCurLineLen;
1952 //if( nCurIndex > nIndex &&
1953 //nLastIndex > nCurLineLen )
1954 if (nCurIndex > nIndex)
1956 if (nLine == 0)
1958 break;
1960 else if (nLine == 1)
1962 aResult.SegmentStart = 0;
1963 aResult.SegmentEnd = nLastIndex;
1964 aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen);
1965 break;
1967 else
1969 //aResult.SegmentStart = nLastIndex - nCurLineLen;
1970 aResult.SegmentStart = nLastIndex - nLastLineLen;
1971 aResult.SegmentEnd = nLastIndex;
1972 aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
1973 break;
1978 break;
1980 case AccessibleTextType::WORD:
1982 nIndex = SkipField( nIndex, false);
1983 OUString sText( implGetText() );
1984 sal_Int32 nLength = sText.getLength();
1986 // get word at index
1987 implGetWordBoundary( aBoundary, nIndex );
1990 //sal_Int32 curWordStart = aBoundary.startPos;
1991 //sal_Int32 preWordStart = curWordStart;
1992 sal_Int32 curWordStart , preWordStart;
1993 if( aBoundary.startPos == -1 || aBoundary.startPos > nIndex)
1994 curWordStart = preWordStart = nIndex;
1995 else
1996 curWordStart = preWordStart = aBoundary.startPos;
1998 // get previous word
2000 bool bWord = false;
2002 //while ( preWordStart > 0 && aBoundary.startPos == curWordStart)
2003 while ( (preWordStart >= 0 && !bWord ) || ( aBoundary.endPos > curWordStart ) )
2005 preWordStart--;
2006 bWord = implGetWordBoundary( aBoundary, preWordStart );
2008 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
2010 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
2011 aResult.SegmentStart = aBoundary.startPos;
2012 aResult.SegmentEnd = aBoundary.endPos;
2013 ExtendByField( aResult );
2016 break;
2017 case AccessibleTextType::CHARACTER:
2019 nIndex = SkipField( nIndex, false);
2020 aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
2021 ExtendByField( aResult );
2022 break;
2024 default:
2025 aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
2026 break;
2027 } /* end of switch( aTextType ) */
2029 return aResult;
2032 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
2034 SolarMutexGuard aGuard;
2036 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2037 "AccessibleEditableTextPara::getTextBehindIndex: paragraph index value overflow");
2039 ::com::sun::star::accessibility::TextSegment aResult;
2040 aResult.SegmentStart = -1;
2041 aResult.SegmentEnd = -1;
2042 i18n::Boundary aBoundary;
2043 switch( aTextType )
2045 case AccessibleTextType::ATTRIBUTE_RUN:
2047 sal_Int32 nStartIndex, nEndIndex;
2049 if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) )
2051 // already at the right border?
2052 if( nEndIndex < GetTextLen() )
2054 if( GetAttributeRun(nStartIndex, nEndIndex, nEndIndex) )
2056 aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex);
2057 aResult.SegmentStart = nStartIndex;
2058 aResult.SegmentEnd = nEndIndex;
2062 break;
2065 case AccessibleTextType::LINE:
2067 SvxTextForwarder& rCacheTF = GetTextForwarder();
2068 sal_Int32 nParaIndex = GetParagraphIndex();
2070 CheckPosition(nIndex);
2072 sal_Int32 nLine, nLineCount = rCacheTF.GetLineCount( nParaIndex );
2073 sal_Int32 nCurIndex;
2074 //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line,
2075 //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed
2076 //by the IAText::attributes(). So here must do special support for bullet line.
2077 sal_Int32 nBulletLen = 0;
2078 // get the line after the line the index points into
2079 for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine )
2081 if (nLine == 0)
2083 EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex);
2084 if (aBulletInfo.bVisible)
2086 //in bullet or numbering;
2087 nBulletLen = aBulletInfo.aText.getLength();
2090 sal_Int32 nLineLen = rCacheTF.GetLineLen( nParaIndex, nLine);
2092 if (nLine == 0)
2093 nCurIndex += nLineLen - nBulletLen;
2094 else
2095 nCurIndex += nLineLen;
2097 if( nCurIndex > nIndex &&
2098 nLine < nLineCount-1 )
2100 aResult.SegmentStart = nCurIndex;
2101 aResult.SegmentEnd = nCurIndex + rCacheTF.GetLineLen( nParaIndex, nLine+1);
2102 aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen);
2103 break;
2107 break;
2109 case AccessibleTextType::WORD:
2111 nIndex = SkipField( nIndex, true);
2112 OUString sText( implGetText() );
2113 sal_Int32 nLength = sText.getLength();
2115 // get word at index
2116 bool bWord = implGetWordBoundary( aBoundary, nIndex );
2118 // real current world
2119 sal_Int32 nextWord = nIndex;
2120 //if( nIndex >= aBoundary.startPos && nIndex <= aBoundary.endPos )
2121 if( nIndex <= aBoundary.endPos )
2123 nextWord = aBoundary.endPos;
2124 if( sText.getStr()[nextWord] == sal_Unicode(' ') ) nextWord++;
2125 bWord = implGetWordBoundary( aBoundary, nextWord );
2128 if ( bWord && implIsValidBoundary( aBoundary, nLength ) )
2130 aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos );
2131 aResult.SegmentStart = aBoundary.startPos;
2132 aResult.SegmentEnd = aBoundary.endPos;
2134 // If the end position of aBoundary is inside a field, extend the result to the end of the field
2136 ExtendByField( aResult );
2139 break;
2141 case AccessibleTextType::CHARACTER:
2143 nIndex = SkipField( nIndex, true);
2144 aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
2145 ExtendByField( aResult );
2146 break;
2148 default:
2149 aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
2150 break;
2151 } /* end of switch( aTextType ) */
2153 return aResult;
2156 sal_Bool SAL_CALL AccessibleEditableTextPara::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2158 SolarMutexGuard aGuard;
2162 SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
2163 #if OSL_DEBUG_LEVEL > 0
2164 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2165 (void)rCacheTF;
2166 #else
2167 GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2168 #endif
2170 bool aRetVal;
2172 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2173 "AccessibleEditableTextPara::copyText: index value overflow");
2175 CheckRange(nStartIndex, nEndIndex);
2177 //Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2178 sal_Int32 nBulletLen = 0;
2179 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2180 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2181 nBulletLen = aBulletInfo.aText.getLength();
2182 // save current selection
2183 ESelection aOldSelection;
2185 rCacheVF.GetSelection( aOldSelection );
2186 //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
2187 rCacheVF.SetSelection( MakeSelection(nStartIndex + nBulletLen, nEndIndex + nBulletLen) );
2188 aRetVal = rCacheVF.Copy();
2189 rCacheVF.SetSelection( aOldSelection ); // restore
2191 return aRetVal;
2193 catch (const uno::RuntimeException&)
2195 return sal_False;
2199 // XAccessibleEditableText
2200 sal_Bool SAL_CALL AccessibleEditableTextPara::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2203 SolarMutexGuard aGuard;
2207 SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
2208 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2210 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2211 "AccessibleEditableTextPara::cutText: index value overflow");
2213 CheckRange(nStartIndex, nEndIndex);
2215 // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2216 sal_Int32 nBulletLen = 0;
2217 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2218 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2219 nBulletLen = aBulletInfo.aText.getLength();
2220 ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
2221 //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
2222 if( !rCacheTF.IsEditable( aSelection ) )
2223 return sal_False; // non-editable area selected
2225 // don't save selection, might become invalid after cut!
2226 //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
2227 rCacheVF.SetSelection( aSelection );
2229 return rCacheVF.Cut();
2231 catch (const uno::RuntimeException&)
2233 return sal_False;
2237 sal_Bool SAL_CALL AccessibleEditableTextPara::pasteText( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2240 SolarMutexGuard aGuard;
2244 SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true );
2245 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2247 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2248 "AccessibleEditableTextPara::pasteText: index value overflow");
2250 CheckPosition(nIndex);
2252 // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2253 sal_Int32 nBulletLen = 0;
2254 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2255 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2256 nBulletLen = aBulletInfo.aText.getLength();
2257 if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) )
2258 return sal_False; // non-editable area selected
2260 // #104400# set empty selection (=> cursor) to given index
2261 //rCacheVF.SetSelection( MakeCursor(nIndex) );
2262 rCacheVF.SetSelection( MakeCursor(nIndex + nBulletLen) );
2264 return rCacheVF.Paste();
2266 catch (const uno::RuntimeException&)
2268 return sal_False;
2272 sal_Bool SAL_CALL AccessibleEditableTextPara::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2275 SolarMutexGuard aGuard;
2279 // #102710# Request edit view when doing changes
2280 // AccessibleEmptyEditSource relies on this behaviour
2281 GetEditViewForwarder( true );
2282 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2284 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2285 "AccessibleEditableTextPara::deleteText: index value overflow");
2287 CheckRange(nStartIndex, nEndIndex);
2289 // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2290 sal_Int32 nBulletLen = 0;
2291 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2292 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2293 nBulletLen = aBulletInfo.aText.getLength();
2294 ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
2296 //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
2297 if( !rCacheTF.IsEditable( aSelection ) )
2298 return sal_False; // non-editable area selected
2300 //sal_Bool bRet = rCacheTF.Delete( MakeSelection(nStartIndex, nEndIndex) );
2301 bool bRet = rCacheTF.Delete( aSelection );
2303 GetEditSource().UpdateData();
2305 return bRet;
2307 catch (const uno::RuntimeException&)
2309 return sal_False;
2313 sal_Bool SAL_CALL AccessibleEditableTextPara::insertText( const OUString& sText, sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2316 SolarMutexGuard aGuard;
2320 // #102710# Request edit view when doing changes
2321 // AccessibleEmptyEditSource relies on this behaviour
2322 GetEditViewForwarder( true );
2323 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2325 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2326 "AccessibleEditableTextPara::insertText: index value overflow");
2328 CheckPosition(nIndex);
2330 // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2331 sal_Int32 nBulletLen = 0;
2332 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2333 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2334 nBulletLen = aBulletInfo.aText.getLength();
2336 if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) )
2337 return sal_False; // non-editable area selected
2339 // #104400# insert given text at empty selection (=> cursor)
2340 bool bRet = rCacheTF.InsertText( sText, MakeCursor(nIndex + nBulletLen) );
2342 rCacheTF.QuickFormatDoc();
2343 GetEditSource().UpdateData();
2345 return bRet;
2347 catch (const uno::RuntimeException&)
2349 return sal_False;
2353 sal_Bool SAL_CALL AccessibleEditableTextPara::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2356 SolarMutexGuard aGuard;
2360 // #102710# Request edit view when doing changes
2361 // AccessibleEmptyEditSource relies on this behaviour
2362 GetEditViewForwarder( true );
2363 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2365 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2366 "AccessibleEditableTextPara::replaceText: index value overflow");
2368 CheckRange(nStartIndex, nEndIndex);
2370 // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet
2371 sal_Int32 nBulletLen = 0;
2372 EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex());
2373 if( aBulletInfo.nParagraph != EE_PARA_NOT_FOUND && aBulletInfo.bVisible )
2374 nBulletLen = aBulletInfo.aText.getLength();
2375 ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen);
2377 //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
2378 if( !rCacheTF.IsEditable( aSelection ) )
2379 return sal_False; // non-editable area selected
2381 // insert given text into given range => replace
2382 //sal_Bool bRet = rCacheTF.InsertText( sReplacement, MakeSelection(nStartIndex, nEndIndex) );
2383 bool bRet = rCacheTF.InsertText( sReplacement, aSelection );
2385 rCacheTF.QuickFormatDoc();
2386 GetEditSource().UpdateData();
2388 return bRet;
2390 catch (const uno::RuntimeException&)
2392 return sal_False;
2396 sal_Bool SAL_CALL AccessibleEditableTextPara::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const uno::Sequence< beans::PropertyValue >& aAttributeSet ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2399 SolarMutexGuard aGuard;
2403 // #102710# Request edit view when doing changes
2404 // AccessibleEmptyEditSource relies on this behaviour
2405 GetEditViewForwarder( true );
2406 SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs
2407 sal_Int32 nPara = GetParagraphIndex();
2409 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2410 "AccessibleEditableTextPara::setAttributes: index value overflow");
2412 CheckRange(nStartIndex, nEndIndex);
2414 if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) )
2415 return sal_False; // non-editable area selected
2417 // do the indices span the whole paragraph? Then use the outliner map
2418 // TODO: hold it as a member?
2419 SvxAccessibleTextPropertySet aPropSet( &GetEditSource(),
2420 0 == nStartIndex &&
2421 rCacheTF.GetTextLen(nPara) == nEndIndex ?
2422 ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() :
2423 ImplGetSvxTextPortionSvxPropertySet() );
2425 aPropSet.SetSelection( MakeSelection(nStartIndex, nEndIndex) );
2427 // convert from PropertyValue to Any
2428 sal_Int32 i, nLength( aAttributeSet.getLength() );
2429 const beans::PropertyValue* pPropArray = aAttributeSet.getConstArray();
2430 for(i=0; i<nLength; ++i)
2434 aPropSet.setPropertyValue(pPropArray->Name, pPropArray->Value);
2436 catch (const uno::Exception&)
2438 OSL_FAIL("AccessibleEditableTextPara::setAttributes exception in setPropertyValue");
2441 ++pPropArray;
2444 rCacheTF.QuickFormatDoc();
2445 GetEditSource().UpdateData();
2447 return sal_True;
2449 catch (const uno::RuntimeException&)
2451 return sal_False;
2455 sal_Bool SAL_CALL AccessibleEditableTextPara::setText( const OUString& sText ) throw (uno::RuntimeException, std::exception)
2458 SolarMutexGuard aGuard;
2460 return replaceText(0, getCharacterCount(), sText);
2463 // XAccessibleTextAttributes
2464 uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDefaultAttributes(
2465 const uno::Sequence< OUString >& rRequestedAttributes )
2466 throw (beans::UnknownPropertyException, uno::RuntimeException, std::exception)
2468 SolarMutexGuard aGuard;
2470 #if OSL_DEBUG_LEVEL > 0
2471 SvxAccessibleTextAdapter& rCacheTF =
2472 #endif
2473 GetTextForwarder();
2475 #if OSL_DEBUG_LEVEL > 0
2476 (void)rCacheTF;
2477 #endif
2479 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2480 "AccessibleEditableTextPara::getCharacterAttributes: index value overflow");
2482 // get XPropertySetInfo for paragraph attributes and
2483 // character attributes that span all the paragraphs text.
2484 SvxAccessibleTextPropertySet aPropSet( &GetEditSource(),
2485 ImplGetSvxCharAndParaPropertiesSet() );
2486 aPropSet.SetSelection( MakeSelection( 0, GetTextLen() ) );
2487 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo();
2488 if (!xPropSetInfo.is())
2489 throw uno::RuntimeException("Cannot query XPropertySetInfo",
2490 uno::Reference< uno::XInterface >
2491 ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
2493 // build sequence of available properties to check
2494 sal_Int32 nLenReqAttr = rRequestedAttributes.getLength();
2495 uno::Sequence< beans::Property > aProperties;
2496 if (nLenReqAttr)
2498 const OUString *pRequestedAttributes = rRequestedAttributes.getConstArray();
2500 aProperties.realloc( nLenReqAttr );
2501 beans::Property *pProperties = aProperties.getArray();
2502 sal_Int32 nCurLen = 0;
2503 for (sal_Int32 i = 0; i < nLenReqAttr; ++i)
2505 beans::Property aProp;
2508 aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] );
2510 catch (const beans::UnknownPropertyException&)
2512 continue;
2514 pProperties[ nCurLen++ ] = aProp;
2516 aProperties.realloc( nCurLen );
2518 else
2519 aProperties = xPropSetInfo->getProperties();
2521 sal_Int32 nLength = aProperties.getLength();
2522 const beans::Property *pProperties = aProperties.getConstArray();
2524 // build resulting sequence
2525 uno::Sequence< beans::PropertyValue > aOutSequence( nLength );
2526 beans::PropertyValue* pOutSequence = aOutSequence.getArray();
2527 sal_Int32 nOutLen = 0;
2528 for (sal_Int32 i = 0; i < nLength; ++i)
2530 // calling implementation functions:
2531 // _getPropertyState and _getPropertyValue (see below) to provide
2532 // the proper paragraph number when retrieving paragraph attributes
2533 PropertyState eState = aPropSet._getPropertyState( pProperties->Name, mnParagraphIndex );
2534 if ( eState == PropertyState_AMBIGUOUS_VALUE )
2536 OSL_FAIL( "ambiguous property value encountered" );
2539 //if (eState == PropertyState_DIRECT_VALUE)
2540 // per definition all paragraph properties and all character
2541 // properties spanning the whole paragraph should be returned
2542 // and declared as default value
2544 pOutSequence->Name = pProperties->Name;
2545 pOutSequence->Handle = pProperties->Handle;
2546 pOutSequence->Value = aPropSet._getPropertyValue( pProperties->Name, mnParagraphIndex );
2547 pOutSequence->State = PropertyState_DEFAULT_VALUE;
2549 ++pOutSequence;
2550 ++nOutLen;
2552 ++pProperties;
2554 aOutSequence.realloc( nOutLen );
2556 return aOutSequence;
2560 uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRunAttributes(
2561 sal_Int32 nIndex,
2562 const uno::Sequence< OUString >& rRequestedAttributes )
2563 throw (beans::UnknownPropertyException, lang::IndexOutOfBoundsException,
2564 uno::RuntimeException, std::exception)
2567 SolarMutexGuard aGuard;
2569 #if OSL_DEBUG_LEVEL > 0
2570 SvxAccessibleTextAdapter& rCacheTF =
2571 #endif
2572 GetTextForwarder();
2574 #if OSL_DEBUG_LEVEL > 0
2575 (void)rCacheTF;
2576 #endif
2578 DBG_ASSERT(GetParagraphIndex() >= 0 && GetParagraphIndex() <= USHRT_MAX,
2579 "AccessibleEditableTextPara::getCharacterAttributes: index value overflow");
2581 if( getCharacterCount() > 0 )
2582 CheckIndex(nIndex);
2583 else
2584 CheckPosition(nIndex);
2586 SvxAccessibleTextPropertySet aPropSet( &GetEditSource(),
2587 ImplGetSvxCharAndParaPropertiesSet() );
2588 aPropSet.SetSelection( MakeSelection( nIndex ) );
2589 uno::Reference< beans::XPropertySetInfo > xPropSetInfo = aPropSet.getPropertySetInfo();
2590 if (!xPropSetInfo.is())
2591 throw uno::RuntimeException("Cannot query XPropertySetInfo",
2592 uno::Reference< uno::XInterface >
2593 ( static_cast< XAccessible* > (this) ) ); // disambiguate hierarchy
2595 // build sequence of available properties to check
2596 sal_Int32 nLenReqAttr = rRequestedAttributes.getLength();
2597 uno::Sequence< beans::Property > aProperties;
2598 if (nLenReqAttr)
2600 const OUString *pRequestedAttributes = rRequestedAttributes.getConstArray();
2602 aProperties.realloc( nLenReqAttr );
2603 beans::Property *pProperties = aProperties.getArray();
2604 sal_Int32 nCurLen = 0;
2605 for (sal_Int32 i = 0; i < nLenReqAttr; ++i)
2607 beans::Property aProp;
2610 aProp = xPropSetInfo->getPropertyByName( pRequestedAttributes[i] );
2612 catch (const beans::UnknownPropertyException&)
2614 continue;
2616 pProperties[ nCurLen++ ] = aProp;
2618 aProperties.realloc( nCurLen );
2620 else
2621 aProperties = xPropSetInfo->getProperties();
2623 sal_Int32 nLength = aProperties.getLength();
2624 const beans::Property *pProperties = aProperties.getConstArray();
2626 // build resulting sequence
2627 uno::Sequence< beans::PropertyValue > aOutSequence( nLength );
2628 beans::PropertyValue* pOutSequence = aOutSequence.getArray();
2629 sal_Int32 nOutLen = 0;
2630 for (sal_Int32 i = 0; i < nLength; ++i)
2632 // calling 'regular' functions that will operate on the selection
2633 PropertyState eState = aPropSet.getPropertyState( pProperties->Name );
2634 if (eState == PropertyState_DIRECT_VALUE)
2636 pOutSequence->Name = pProperties->Name;
2637 pOutSequence->Handle = pProperties->Handle;
2638 pOutSequence->Value = aPropSet.getPropertyValue( pProperties->Name );
2639 pOutSequence->State = eState;
2641 ++pOutSequence;
2642 ++nOutLen;
2644 ++pProperties;
2646 aOutSequence.realloc( nOutLen );
2648 return aOutSequence;
2651 // XAccessibleHypertext
2652 ::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkCount( ) throw (::com::sun::star::uno::RuntimeException, std::exception)
2654 SvxAccessibleTextAdapter& rT = GetTextForwarder();
2655 const sal_Int32 nPara = GetParagraphIndex();
2657 sal_Int32 nHyperLinks = 0;
2658 sal_Int32 nFields = rT.GetFieldCount( nPara );
2659 for (sal_Int32 n = 0; n < nFields; ++n)
2661 EFieldInfo aField = rT.GetFieldInfo( nPara, n );
2662 if ( aField.pFieldItem->GetField()->ISA( SvxURLField ) )
2663 nHyperLinks++;
2665 return nHyperLinks;
2668 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleHyperlink > SAL_CALL AccessibleEditableTextPara::getHyperLink( ::sal_Int32 nLinkIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
2670 ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessibleHyperlink > xRef;
2672 SvxAccessibleTextAdapter& rT = GetTextForwarder();
2673 const sal_Int32 nPara = GetParagraphIndex();
2675 sal_Int32 nHyperLink = 0;
2676 sal_Int32 nFields = rT.GetFieldCount( nPara );
2677 for (sal_Int32 n = 0; n < nFields; ++n)
2679 EFieldInfo aField = rT.GetFieldInfo( nPara, n );
2680 if ( aField.pFieldItem->GetField()->ISA( SvxURLField ) )
2682 if ( nHyperLink == nLinkIndex )
2684 sal_Int32 nEEStart = aField.aPosition.nIndex;
2686 // Translate EE Index to accessible index
2687 sal_Int32 nStart = rT.CalcEditEngineIndex( nPara, nEEStart );
2688 sal_Int32 nEnd = nStart + aField.aCurrentText.getLength();
2689 xRef = new AccessibleHyperlink( rT, new SvxFieldItem( *aField.pFieldItem ), nPara, nEEStart, nStart, nEnd, aField.aCurrentText );
2690 break;
2692 nHyperLink++;
2696 return xRef;
2699 ::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkIndex( ::sal_Int32 nCharIndex ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException, std::exception)
2701 const sal_Int32 nPara = GetParagraphIndex();
2702 SvxAccessibleTextAdapter& rT = GetTextForwarder();
2704 const sal_Int32 nEEIndex = rT.CalcEditEngineIndex( nPara, nCharIndex );
2705 sal_Int32 nHLIndex = -1; //i123620
2706 sal_Int32 nHyperLink = 0;
2707 sal_Int32 nFields = rT.GetFieldCount( nPara );
2708 for (sal_Int32 n = 0; n < nFields; ++n)
2710 EFieldInfo aField = rT.GetFieldInfo( nPara, n );
2711 if ( aField.pFieldItem->GetField()->ISA( SvxURLField ) )
2713 if ( aField.aPosition.nIndex == nEEIndex )
2715 nHLIndex = nHyperLink;
2716 break;
2718 nHyperLink++;
2722 return nHLIndex;
2725 // XAccessibleMultiLineText
2726 sal_Int32 SAL_CALL AccessibleEditableTextPara::getLineNumberAtIndex( sal_Int32 nIndex ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2729 sal_Int32 nRes = -1;
2730 sal_Int32 nPara = GetParagraphIndex();
2732 SvxTextForwarder &rCacheTF = GetTextForwarder();
2733 const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount();
2734 DBG_ASSERT( bValidPara, "getLineNumberAtIndex: current paragraph index out of range" );
2735 if (bValidPara)
2737 // we explicitly allow for the index to point at the character right behind the text
2738 if (0 <= nIndex && nIndex <= rCacheTF.GetTextLen( nPara ))
2739 nRes = rCacheTF.GetLineNumberAtIndex( nPara, nIndex );
2740 else
2741 throw lang::IndexOutOfBoundsException();
2743 return nRes;
2746 // XAccessibleMultiLineText
2747 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineNumber( sal_Int32 nLineNo ) throw (lang::IndexOutOfBoundsException, uno::RuntimeException, std::exception)
2750 ::com::sun::star::accessibility::TextSegment aResult;
2751 sal_Int32 nPara = GetParagraphIndex();
2752 SvxTextForwarder &rCacheTF = GetTextForwarder();
2753 const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount();
2754 DBG_ASSERT( bValidPara, "getTextAtLineNumber: current paragraph index out of range" );
2755 if (bValidPara)
2757 if (0 <= nLineNo && nLineNo < rCacheTF.GetLineCount( nPara ))
2759 sal_Int32 nStart = 0, nEnd = 0;
2760 rCacheTF.GetLineBoundaries( nStart, nEnd, nPara, nLineNo );
2761 if (nStart >= 0 && nEnd >= 0)
2765 aResult.SegmentText = getTextRange( nStart, nEnd );
2766 aResult.SegmentStart = nStart;
2767 aResult.SegmentEnd = nEnd;
2769 catch (const lang::IndexOutOfBoundsException&)
2771 // this is not the exception that should be raised in this function ...
2772 DBG_ASSERT( false, "unexpected exception" );
2776 else
2777 throw lang::IndexOutOfBoundsException();
2779 return aResult;
2782 // XAccessibleMultiLineText
2783 ::com::sun::star::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineWithCaret( ) throw (uno::RuntimeException, std::exception)
2786 ::com::sun::star::accessibility::TextSegment aResult;
2789 aResult = getTextAtLineNumber( getNumberOfLineWithCaret() );
2791 catch (const lang::IndexOutOfBoundsException&)
2793 // this one needs to be catched since this interface does not allow for it.
2795 return aResult;
2798 // XAccessibleMultiLineText
2799 sal_Int32 SAL_CALL AccessibleEditableTextPara::getNumberOfLineWithCaret( ) throw (uno::RuntimeException, std::exception)
2802 sal_Int32 nRes = -1;
2805 nRes = getLineNumberAtIndex( getCaretPosition() );
2807 catch (const lang::IndexOutOfBoundsException&)
2809 // this one needs to be catched since this interface does not allow for it.
2811 return nRes;
2815 // XServiceInfo
2816 OUString SAL_CALL AccessibleEditableTextPara::getImplementationName() throw (uno::RuntimeException, std::exception)
2819 return OUString("AccessibleEditableTextPara");
2822 sal_Bool SAL_CALL AccessibleEditableTextPara::supportsService (const OUString& sServiceName) throw (uno::RuntimeException, std::exception)
2825 return cppu::supportsService(this, sServiceName);
2828 uno::Sequence< OUString> SAL_CALL AccessibleEditableTextPara::getSupportedServiceNames() throw (uno::RuntimeException, std::exception)
2831 const OUString sServiceName( getServiceName() );
2832 return uno::Sequence< OUString > (&sServiceName, 1);
2835 // XServiceName
2836 OUString SAL_CALL AccessibleEditableTextPara::getServiceName() throw (uno::RuntimeException)
2839 // #105185# Using correct service now
2840 return OUString("com.sun.star.text.AccessibleParagraphView");
2843 } // end of namespace accessibility
2847 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */