1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: textwindowaccessibility.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_accessibility.hxx"
34 #ifndef _TOOLKIT_AWT_VCLXACCESSIBLECOMPONENT_HXX_
35 #include <accessibility/extended/textwindowaccessibility.hxx>
37 #include "comphelper/accessibleeventnotifier.hxx"
38 #include "unotools/accessiblerelationsethelper.hxx"
39 #include <unotools/accessiblestatesethelper.hxx>
40 #include <vcl/window.hxx>
41 #include <toolkit/helper/convert.hxx>
47 namespace css
= ::com::sun::star
;
49 namespace accessibility
52 // Both ::osl::Mutex and ParagraphBase implement acquire and release, and thus
53 // ::rtl::Reference< Paragraph > does not work. So ParagraphImpl was factored
54 // out and ::rtl::Reference< ParagraphImpl > is used instead.
55 class Paragraph
: private ::osl::Mutex
, public ParagraphImpl
58 inline Paragraph(::rtl::Reference
< Document
> const & rDocument
,
59 Paragraphs::size_type nNumber
):
60 ParagraphImpl(rDocument
, nNumber
, *this) {}
63 void SfxListenerGuard::startListening(::SfxBroadcaster
& rNotifier
)
65 OSL_ENSURE(m_pNotifier
== 0, "called more than once");
66 m_pNotifier
= &rNotifier
;
67 m_rListener
.StartListening(*m_pNotifier
, true);
70 void SfxListenerGuard::endListening()
74 m_rListener
.EndListening(*m_pNotifier
);
79 void WindowListenerGuard::startListening(::Window
& rNotifier
)
81 OSL_ENSURE(m_pNotifier
== 0, "called more than once");
82 m_pNotifier
= &rNotifier
;
83 m_pNotifier
->AddEventListener(m_aListener
);
86 void WindowListenerGuard::endListening()
90 m_pNotifier
->RemoveEventListener(m_aListener
);
95 ParagraphImpl::ParagraphImpl(::rtl::Reference
< Document
> const & rDocument
,
96 Paragraphs::size_type nNumber
,
97 ::osl::Mutex
& rMutex
):
98 ParagraphBase(rMutex
),
99 m_xDocument(rDocument
),
103 m_aParagraphText
= m_xDocument
->retrieveParagraphText(this);
107 ParagraphImpl::numberChanged(bool bIncremented
)
115 void ParagraphImpl::textChanged()
117 ::rtl::OUString aParagraphText
= implGetText();
118 ::css::uno::Any aOldValue
, aNewValue
;
119 if ( implInitTextChangedEvent( m_aParagraphText
, aParagraphText
, aOldValue
, aNewValue
) )
121 m_aParagraphText
= aParagraphText
;
122 notifyEvent(::css::accessibility::AccessibleEventId::
124 aOldValue
, aNewValue
);
128 void ParagraphImpl::notifyEvent(::sal_Int16 nEventId
,
129 ::css::uno::Any
const & rOldValue
,
130 ::css::uno::Any
const & rNewValue
)
133 comphelper::AccessibleEventNotifier::addEvent( m_nClientId
, ::css::accessibility::AccessibleEventObject(
134 static_cast< ::cppu::OWeakObject
* >(this),
135 nEventId
, rNewValue
, rOldValue
) );
139 ::css::uno::Reference
< ::css::accessibility::XAccessibleContext
> SAL_CALL
140 ParagraphImpl::getAccessibleContext() throw (::css::uno::RuntimeException
)
147 ::sal_Int32 SAL_CALL
ParagraphImpl::getAccessibleChildCount()
148 throw (::css::uno::RuntimeException
)
155 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
156 ParagraphImpl::getAccessibleChild(::sal_Int32
)
157 throw (::css::lang::IndexOutOfBoundsException
,
158 ::css::uno::RuntimeException
)
161 throw ::css::lang::IndexOutOfBoundsException(
163 RTL_CONSTASCII_USTRINGPARAM(
164 "textwindowaccessibility.cxx:"
165 " ParagraphImpl::getAccessibleChild")),
166 static_cast< ::css::uno::XWeak
* >(this));
170 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
171 ParagraphImpl::getAccessibleParent()
172 throw (::css::uno::RuntimeException
)
175 return m_xDocument
->getAccessible();
179 ::sal_Int32 SAL_CALL
ParagraphImpl::getAccessibleIndexInParent()
180 throw (::css::uno::RuntimeException
)
183 return m_xDocument
->retrieveParagraphIndex(this);
187 ::sal_Int16 SAL_CALL
ParagraphImpl::getAccessibleRole()
188 throw (::css::uno::RuntimeException
)
191 return ::css::accessibility::AccessibleRole::PARAGRAPH
;
195 ::rtl::OUString SAL_CALL
ParagraphImpl::getAccessibleDescription()
196 throw (::css::uno::RuntimeException
)
199 return ::rtl::OUString();
203 ::rtl::OUString SAL_CALL
ParagraphImpl::getAccessibleName()
204 throw (::css::uno::RuntimeException
)
207 return ::rtl::OUString();
211 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
>
212 SAL_CALL
ParagraphImpl::getAccessibleRelationSet()
213 throw (::css::uno::RuntimeException
)
216 return m_xDocument
->retrieveParagraphRelationSet( this );
220 ::css::uno::Reference
< ::css::accessibility::XAccessibleStateSet
>
221 SAL_CALL
ParagraphImpl::getAccessibleStateSet()
222 throw (::css::uno::RuntimeException
)
226 // FIXME Notification of changes (STATE_CHANGED) missing when
227 // m_rView.IsReadOnly() changes:
228 return new ::utl::AccessibleStateSetHelper(
229 m_xDocument
->retrieveParagraphState(this));
233 ::css::lang::Locale SAL_CALL
ParagraphImpl::getLocale()
234 throw (::css::accessibility::IllegalAccessibleComponentStateException
,
235 ::css::uno::RuntimeException
)
238 return m_xDocument
->retrieveLocale();
242 ::sal_Bool SAL_CALL
ParagraphImpl::containsPoint(::css::awt::Point
const & rPoint
)
243 throw (::css::uno::RuntimeException
)
246 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
248 return rPoint
.X
>= 0 && rPoint
.X
< aRect
.Width
249 && rPoint
.Y
>= 0 && rPoint
.Y
< aRect
.Height
;
253 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
254 ParagraphImpl::getAccessibleAtPoint(::css::awt::Point
const &)
255 throw (::css::uno::RuntimeException
)
262 ::css::awt::Rectangle SAL_CALL
ParagraphImpl::getBounds()
263 throw (::css::uno::RuntimeException
)
266 return m_xDocument
->retrieveParagraphBounds(this, false);
270 ::css::awt::Point SAL_CALL
ParagraphImpl::getLocation()
271 throw (::css::uno::RuntimeException
)
274 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
276 return ::css::awt::Point(aRect
.X
, aRect
.Y
);
280 ::css::awt::Point SAL_CALL
ParagraphImpl::getLocationOnScreen()
281 throw (::css::uno::RuntimeException
)
284 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
286 return ::css::awt::Point(aRect
.X
, aRect
.Y
);
290 ::css::awt::Size SAL_CALL
ParagraphImpl::getSize()
291 throw (::css::uno::RuntimeException
)
294 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
296 return ::css::awt::Size(aRect
.Width
, aRect
.Height
);
300 void SAL_CALL
ParagraphImpl::grabFocus() throw (::css::uno::RuntimeException
)
303 Window
* pWindow
= m_xDocument
->GetWindow();
306 pWindow
->GrabFocus();
310 m_xDocument
->changeParagraphSelection(this, 0, 0);
312 catch (::css::lang::IndexOutOfBoundsException
& rEx
)
315 "textwindowaccessibility.cxx: ParagraphImpl::grabFocus:"
316 " caught unexpected %s\n",
317 ::rtl::OUStringToOString(rEx
.Message
, RTL_TEXTENCODING_UTF8
).
323 ::css::uno::Any SAL_CALL
ParagraphImpl::getAccessibleKeyBinding()
324 throw (::css::uno::RuntimeException
)
327 return ::css::uno::Any();
331 ::css::util::Color SAL_CALL
ParagraphImpl::getForeground()
332 throw (::css::uno::RuntimeException
)
338 ::css::util::Color SAL_CALL
ParagraphImpl::getBackground()
339 throw (::css::uno::RuntimeException
)
345 ::sal_Int32 SAL_CALL
ParagraphImpl::getCaretPosition()
346 throw (::css::uno::RuntimeException
)
349 return m_xDocument
->retrieveParagraphCaretPosition(this);
353 ::sal_Bool SAL_CALL
ParagraphImpl::setCaretPosition(::sal_Int32 nIndex
)
354 throw (::css::lang::IndexOutOfBoundsException
,
355 ::css::uno::RuntimeException
)
358 m_xDocument
->changeParagraphSelection(this, nIndex
, nIndex
);
363 ::sal_Unicode SAL_CALL
ParagraphImpl::getCharacter(::sal_Int32 nIndex
)
364 throw (::css::lang::IndexOutOfBoundsException
,
365 ::css::uno::RuntimeException
)
368 return OCommonAccessibleText::getCharacter(nIndex
);
372 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
373 ParagraphImpl::getCharacterAttributes(::sal_Int32 nIndex
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
)
374 throw (::css::lang::IndexOutOfBoundsException
,
375 ::css::uno::RuntimeException
)
378 return m_xDocument
->retrieveCharacterAttributes( this, nIndex
, aRequestedAttributes
);
382 ::css::awt::Rectangle SAL_CALL
383 ParagraphImpl::getCharacterBounds(::sal_Int32 nIndex
)
384 throw (::css::lang::IndexOutOfBoundsException
,
385 ::css::uno::RuntimeException
)
388 ::css::awt::Rectangle
aBounds(m_xDocument
->retrieveCharacterBounds(this, nIndex
));
389 ::css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
390 aBounds
.X
-= aParaBounds
.X
;
391 aBounds
.Y
-= aParaBounds
.Y
;
396 ::sal_Int32 SAL_CALL
ParagraphImpl::getCharacterCount()
397 throw (::css::uno::RuntimeException
)
400 return OCommonAccessibleText::getCharacterCount();
405 ParagraphImpl::getIndexAtPoint(::css::awt::Point
const & rPoint
)
406 throw (::css::uno::RuntimeException
)
409 ::css::awt::Point
aPoint(rPoint
);
410 ::css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
411 aPoint
.X
+= aParaBounds
.X
;
412 aPoint
.Y
+= aParaBounds
.Y
;
413 return m_xDocument
->retrieveCharacterIndex(this, aPoint
);
417 ::rtl::OUString SAL_CALL
ParagraphImpl::getSelectedText()
418 throw (::css::uno::RuntimeException
)
422 return OCommonAccessibleText::getSelectedText();
426 ::sal_Int32 SAL_CALL
ParagraphImpl::getSelectionStart()
427 throw (::css::uno::RuntimeException
)
430 return OCommonAccessibleText::getSelectionStart();
434 ::sal_Int32 SAL_CALL
ParagraphImpl::getSelectionEnd()
435 throw (::css::uno::RuntimeException
)
438 return OCommonAccessibleText::getSelectionEnd();
442 ::sal_Bool SAL_CALL
ParagraphImpl::setSelection(::sal_Int32 nStartIndex
,
443 ::sal_Int32 nEndIndex
)
444 throw (::css::lang::IndexOutOfBoundsException
,
445 ::css::uno::RuntimeException
)
448 m_xDocument
->changeParagraphSelection(this, nStartIndex
, nEndIndex
);
453 ::rtl::OUString SAL_CALL
ParagraphImpl::getText()
454 throw (::css::uno::RuntimeException
)
457 return OCommonAccessibleText::getText();
461 ::rtl::OUString SAL_CALL
ParagraphImpl::getTextRange(::sal_Int32 nStartIndex
,
462 ::sal_Int32 nEndIndex
)
463 throw (::css::lang::IndexOutOfBoundsException
,
464 ::css::uno::RuntimeException
)
467 return OCommonAccessibleText::getTextRange(nStartIndex
, nEndIndex
);
471 ::com::sun::star::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
474 return OCommonAccessibleText::getTextAtIndex(nIndex
, aTextType
);
478 ::com::sun::star::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
481 return OCommonAccessibleText::getTextBeforeIndex(nIndex
, aTextType
);
485 ::com::sun::star::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
)
488 return OCommonAccessibleText::getTextBehindIndex(nIndex
, aTextType
);
492 ::sal_Bool SAL_CALL
ParagraphImpl::copyText(::sal_Int32 nStartIndex
,
493 ::sal_Int32 nEndIndex
)
494 throw (::css::lang::IndexOutOfBoundsException
,
495 ::css::uno::RuntimeException
)
498 m_xDocument
->copyParagraphText(this, nStartIndex
, nEndIndex
);
503 ::sal_Bool SAL_CALL
ParagraphImpl::cutText(::sal_Int32 nStartIndex
,
504 ::sal_Int32 nEndIndex
)
505 throw (::css::lang::IndexOutOfBoundsException
,
506 ::css::uno::RuntimeException
)
509 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, true, false,
515 ::sal_Bool SAL_CALL
ParagraphImpl::pasteText(::sal_Int32 nIndex
)
516 throw (::css::lang::IndexOutOfBoundsException
,
517 ::css::uno::RuntimeException
)
520 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, true,
526 ::sal_Bool SAL_CALL
ParagraphImpl::deleteText(::sal_Int32 nStartIndex
,
527 ::sal_Int32 nEndIndex
)
528 throw (::css::lang::IndexOutOfBoundsException
,
529 ::css::uno::RuntimeException
)
532 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
538 ::sal_Bool SAL_CALL
ParagraphImpl::insertText(::rtl::OUString
const & rText
,
540 throw (::css::lang::IndexOutOfBoundsException
,
541 ::css::uno::RuntimeException
)
544 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, false, rText
);
550 ParagraphImpl::replaceText(::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
551 ::rtl::OUString
const & rReplacement
)
552 throw (::css::lang::IndexOutOfBoundsException
,
553 ::css::uno::RuntimeException
)
556 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
562 ::sal_Bool SAL_CALL
ParagraphImpl::setAttributes(
563 ::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
564 ::css::uno::Sequence
< ::css::beans::PropertyValue
> const & rAttributeSet
)
565 throw (::css::lang::IndexOutOfBoundsException
,
566 ::css::uno::RuntimeException
)
569 m_xDocument
->changeParagraphAttributes(this, nStartIndex
, nEndIndex
,
575 ::sal_Bool SAL_CALL
ParagraphImpl::setText(::rtl::OUString
const & rText
)
576 throw (::css::uno::RuntimeException
)
579 m_xDocument
->changeParagraphText(this, rText
);
584 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
585 ParagraphImpl::getDefaultAttributes(const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
)
586 throw (::css::uno::RuntimeException
)
589 return m_xDocument
->retrieveDefaultAttributes( this, RequestedAttributes
);
593 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
594 ParagraphImpl::getRunAttributes(::sal_Int32 Index
, const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
)
595 throw (::css::lang::IndexOutOfBoundsException
,
596 ::css::uno::RuntimeException
)
599 return m_xDocument
->retrieveRunAttributes( this, Index
, RequestedAttributes
);
603 ::sal_Int32 SAL_CALL
ParagraphImpl::getLineNumberAtIndex( ::sal_Int32 nIndex
)
604 throw (::css::lang::IndexOutOfBoundsException
,
605 ::css::uno::RuntimeException
)
609 ::sal_Int32 nLineNo
= -1;
610 ::css::i18n::Boundary aBoundary
=
611 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
, &nLineNo
);
617 ::css::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextAtLineNumber( ::sal_Int32 nLineNo
)
618 throw (::css::lang::IndexOutOfBoundsException
,
619 ::css::uno::RuntimeException
)
623 ::css::i18n::Boundary aBoundary
=
624 m_xDocument
->retrieveParagraphBoundaryOfLine( this, nLineNo
);
626 return ::css::accessibility::TextSegment( getTextRange(aBoundary
.startPos
, aBoundary
.endPos
),
627 aBoundary
.startPos
, aBoundary
.endPos
);
631 ::css::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextAtLineWithCaret( )
632 throw (::css::uno::RuntimeException
)
636 sal_Int32 nLineNo
= getNumberOfLineWithCaret();
639 return ( nLineNo
>= 0 ) ?
640 getTextAtLineNumber( nLineNo
) :
641 ::css::accessibility::TextSegment();
642 } catch (const ::css::lang::IndexOutOfBoundsException
&) {
643 throw ::css::uno::RuntimeException(
645 RTL_CONSTASCII_USTRINGPARAM(
646 "textwindowaccessibility.cxx:"
647 " ParagraphImpl::getTextAtLineWithCaret") ),
648 static_cast< ::css::uno::XWeak
* >( this ) );
653 ::sal_Int32 SAL_CALL
ParagraphImpl::getNumberOfLineWithCaret( )
654 throw (::css::uno::RuntimeException
)
657 return m_xDocument
->retrieveParagraphLineWithCursor(this);
662 void SAL_CALL
ParagraphImpl::addEventListener(
663 ::css::uno::Reference
<
664 ::css::accessibility::XAccessibleEventListener
> const & rListener
)
665 throw (::css::uno::RuntimeException
)
669 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
670 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
673 rListener
->disposing(::css::lang::EventObject(
674 static_cast< ::cppu::OWeakObject
* >(this)));
679 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
680 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, rListener
);
686 void SAL_CALL
ParagraphImpl::removeEventListener(
687 ::css::uno::Reference
<
688 ::css::accessibility::XAccessibleEventListener
> const & rListener
)
689 throw (::css::uno::RuntimeException
)
691 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
693 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
694 if (rListener
.is() && m_nClientId
!= 0
695 && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, rListener
) == 0)
703 // no listeners anymore
704 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
705 // and at least to us not firing any events anymore, in case somebody calls
706 // NotifyAccessibleEvent, again
707 comphelper::AccessibleEventNotifier::revokeClient(nId
);
712 void SAL_CALL
ParagraphImpl::disposing()
714 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
716 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
721 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId
, *this);
725 ::rtl::OUString
ParagraphImpl::implGetText()
727 return m_xDocument
->retrieveParagraphText(this);
731 ::css::lang::Locale
ParagraphImpl::implGetLocale()
733 return m_xDocument
->retrieveLocale();
737 void ParagraphImpl::implGetSelection(::sal_Int32
& rStartIndex
,
738 ::sal_Int32
& rEndIndex
)
740 m_xDocument
->retrieveParagraphSelection(this, &rStartIndex
, &rEndIndex
);
744 void ParagraphImpl::implGetParagraphBoundary( ::css::i18n::Boundary
& rBoundary
,
747 ::rtl::OUString
sText( implGetText() );
748 ::sal_Int32 nLength
= sText
.getLength();
750 if ( implIsValidIndex( nIndex
, nLength
) )
752 rBoundary
.startPos
= 0;
753 rBoundary
.endPos
= nLength
;
757 rBoundary
.startPos
= nIndex
;
758 rBoundary
.endPos
= nIndex
;
763 void ParagraphImpl::implGetLineBoundary( ::css::i18n::Boundary
& rBoundary
,
766 ::rtl::OUString
sText( implGetText() );
767 ::sal_Int32 nLength
= sText
.getLength();
769 if ( implIsValidIndex( nIndex
, nLength
) || nIndex
== nLength
)
771 ::css::i18n::Boundary aBoundary
=
772 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
);
773 rBoundary
.startPos
= aBoundary
.startPos
;
774 rBoundary
.endPos
= aBoundary
.endPos
;
778 rBoundary
.startPos
= nIndex
;
779 rBoundary
.endPos
= nIndex
;
784 void ParagraphImpl::checkDisposed()
786 ::osl::MutexGuard
aGuard(rBHelper
.rMutex
);
787 if (!(rBHelper
.bDisposed
|| rBHelper
.bInDispose
))
789 throw ::css::lang::DisposedException(
790 ::rtl::OUString(), static_cast< ::css::uno::XWeak
* >(this));
793 Document::Document(::VCLXWindow
* pVclXWindow
, ::TextEngine
& rEngine
,
794 ::TextView
& rView
, bool bCompoundControlChild
):
795 VCLXAccessibleComponent(pVclXWindow
),
796 m_xAccessible(pVclXWindow
),
799 m_aEngineListener(*this),
800 m_aViewListener(LINK(this, Document
, WindowEventHandler
)),
801 m_bCompoundControlChild(bCompoundControlChild
)
804 ::css::lang::Locale
Document::retrieveLocale()
806 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
807 return m_rEngine
.GetLocale();
810 ::sal_Int32
Document::retrieveParagraphIndex(ParagraphImpl
const * pParagraph
)
812 ::osl::MutexGuard
aInternalGuard(GetMutex());
814 // If a client holds on to a Paragraph that is no longer visible, it can
815 // happen that this Paragraph lies outside the range from m_aVisibleBegin
816 // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
817 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
818 + pParagraph
->getNumber());
819 return aPara
< m_aVisibleBegin
|| aPara
>= m_aVisibleEnd
820 ? -1 : static_cast< ::sal_Int32
>(aPara
- m_aVisibleBegin
);
821 // XXX numeric overflow
824 ::sal_Int64
Document::retrieveParagraphState(ParagraphImpl
const * pParagraph
)
826 ::osl::MutexGuard
aInternalGuard(GetMutex());
828 // If a client holds on to a Paragraph that is no longer visible, it can
829 // happen that this Paragraph lies outside the range from m_aVisibleBegin
830 // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
832 = (static_cast< ::sal_Int64
>(1)
833 << ::css::accessibility::AccessibleStateType::ENABLED
)
834 | (static_cast< ::sal_Int64
>(1)
835 << ::css::accessibility::AccessibleStateType::SENSITIVE
)
836 | (static_cast< ::sal_Int64
>(1)
837 << ::css::accessibility::AccessibleStateType::FOCUSABLE
)
838 | (static_cast< ::sal_Int64
>(1)
839 << ::css::accessibility::AccessibleStateType::MULTI_LINE
);
840 if (!m_rView
.IsReadOnly())
841 nState
|= (static_cast< ::sal_Int64
>(1)
842 << ::css::accessibility::AccessibleStateType::EDITABLE
);
843 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
844 + pParagraph
->getNumber());
845 if (aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
848 |= (static_cast< ::sal_Int64
>(1)
849 << ::css::accessibility::AccessibleStateType::VISIBLE
)
850 | (static_cast< ::sal_Int64
>(1)
851 << ::css::accessibility::AccessibleStateType::SHOWING
);
852 if (aPara
== m_aFocused
)
853 nState
|= (static_cast< ::sal_Int64
>(1)
854 << ::css::accessibility::AccessibleStateType::FOCUSED
);
859 ::css::awt::Rectangle
860 Document::retrieveParagraphBounds(ParagraphImpl
const * pParagraph
,
863 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
864 ::osl::MutexGuard
aInternalGuard(GetMutex());
866 // If a client holds on to a Paragraph that is no longer visible (as it
867 // scrolled out the top of the view), it can happen that this Paragraph
868 // lies before m_aVisibleBegin. In that case, calculate the vertical
869 // position of the Paragraph starting at paragraph 0, otherwise optimize
870 // and start at m_aVisibleBegin:
871 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
872 + pParagraph
->getNumber());
874 Paragraphs::iterator aIt
;
875 if (aPara
< m_aVisibleBegin
)
878 aIt
= m_xParagraphs
->begin();
882 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
883 aIt
= m_aVisibleBegin
;
885 for (; aIt
!= aPara
; ++aIt
)
886 nPos
+= aIt
->getHeight();
890 aOrig
= m_rView
.GetWindow()->OutputToAbsoluteScreenPixel(aOrig
);
892 return ::css::awt::Rectangle(
893 static_cast< ::sal_Int32
>(aOrig
.X()),
894 static_cast< ::sal_Int32
>(aOrig
.Y()) + nPos
- m_nViewOffset
,
895 m_rView
.GetWindow()->GetOutputSizePixel().Width(), aPara
->getHeight());
896 // XXX numeric overflow (3x)
900 Document::retrieveParagraphText(ParagraphImpl
const * pParagraph
)
902 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
903 ::osl::MutexGuard
aInternalGuard(GetMutex());
904 return m_rEngine
.GetText(static_cast< ::ULONG
>(pParagraph
->getNumber()));
905 // numeric overflow cannot happen here
908 void Document::retrieveParagraphSelection(ParagraphImpl
const * pParagraph
,
909 ::sal_Int32
* pBegin
,
912 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
913 ::osl::MutexGuard
aInternalGuard(GetMutex());
914 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
915 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
916 TextPaM
aStartPaM( rSelection
.GetStart() );
917 TextPaM
aEndPaM( rSelection
.GetEnd() );
918 TextPaM
aMinPaM( ::std::min( aStartPaM
, aEndPaM
) );
919 TextPaM
aMaxPaM( ::std::max( aStartPaM
, aEndPaM
) );
921 if ( nNumber
>= aMinPaM
.GetPara() && nNumber
<= aMaxPaM
.GetPara() )
923 *pBegin
= nNumber
> aMinPaM
.GetPara()
925 : static_cast< ::sal_Int32
>( aMinPaM
.GetIndex() );
926 // XXX numeric overflow
927 *pEnd
= nNumber
< aMaxPaM
.GetPara()
928 ? static_cast< ::sal_Int32
>( m_rEngine
.GetText(static_cast< ::ULONG
>(nNumber
)).Len() )
929 : static_cast< ::sal_Int32
>( aMaxPaM
.GetIndex() );
930 // XXX numeric overflow (3x)
932 if ( aStartPaM
> aEndPaM
)
933 ::std::swap( *pBegin
, *pEnd
);
942 ::sal_Int32
Document::retrieveParagraphCaretPosition(ParagraphImpl
const * pParagraph
)
944 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
945 ::osl::MutexGuard
aInternalGuard(GetMutex());
946 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
947 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
948 TextPaM
aEndPaM( rSelection
.GetEnd() );
950 return aEndPaM
.GetPara() == nNumber
951 ? static_cast< ::sal_Int32
>(aEndPaM
.GetIndex()) : -1;
954 ::css::awt::Rectangle
955 Document::retrieveCharacterBounds(ParagraphImpl
const * pParagraph
,
958 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
959 ::osl::MutexGuard
aInternalGuard(GetMutex());
960 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
961 sal_Int32 nLength
= m_rEngine
.GetText(nNumber
).Len();
962 // XXX numeric overflow
963 if (nIndex
< 0 || nIndex
> nLength
)
964 throw ::css::lang::IndexOutOfBoundsException(
966 RTL_CONSTASCII_USTRINGPARAM(
967 "textwindowaccessibility.cxx:"
968 " Document::retrieveCharacterAttributes")),
969 static_cast< ::css::uno::XWeak
* >(this));
970 ::css::awt::Rectangle
aBounds( 0, 0, 0, 0 );
971 if ( nIndex
== nLength
)
973 aBounds
= AWTRectangle(
974 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
975 static_cast< ::USHORT
>(nIndex
))));
980 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
981 static_cast< ::USHORT
>(nIndex
))));
982 // XXX numeric overflow
984 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
985 static_cast< ::USHORT
>(nIndex
)
987 // XXX numeric overflow (2x)
988 // FIXME If the vertical extends of the two cursors do not match, assume
989 // nIndex is the last character on the line; the bounding box will then
990 // extend to m_rEnginge.GetMaxTextWidth():
991 ::sal_Int32 nWidth
= (aLeft
.Top() == aRight
.Top()
992 && aLeft
.Bottom() == aRight
.Bottom())
993 ? static_cast< ::sal_Int32
>(aRight
.Left() - aLeft
.Left())
994 : static_cast< ::sal_Int32
>(m_rEngine
.GetMaxTextWidth()
996 // XXX numeric overflow (4x)
997 aBounds
= ::css::awt::Rectangle(static_cast< ::sal_Int32
>(aLeft
.Left()),
998 static_cast< ::sal_Int32
>(aLeft
.Top() - m_nViewOffset
),
1000 static_cast< ::sal_Int32
>(aLeft
.Bottom()
1002 // XXX numeric overflow (4x)
1007 ::sal_Int32
Document::retrieveCharacterIndex(ParagraphImpl
const * pParagraph
,
1008 ::css::awt::Point
const & rPoint
)
1010 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1011 ::osl::MutexGuard
aInternalGuard(GetMutex());
1012 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1013 // XXX numeric overflow
1014 ::TextPaM
aPaM(m_rEngine
.GetPaM(::Point(static_cast< long >(rPoint
.X
),
1015 static_cast< long >(rPoint
.Y
))));
1016 // XXX numeric overflow (2x)
1017 return aPaM
.GetPara() == nNumber
1018 ? static_cast< ::sal_Int32
>(aPaM
.GetIndex()) : -1;
1019 // XXX numeric overflow
1022 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1023 Document::retrieveCharacterAttributes(
1024 ParagraphImpl
const * pParagraph
, ::sal_Int32 nIndex
,
1025 const ::css::uno::Sequence
< ::rtl::OUString
>& aRequestedAttributes
)
1027 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1028 ::osl::MutexGuard
aInternalGuard(GetMutex());
1029 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1030 // XXX numeric overflow
1031 if (nIndex
< 0 || nIndex
>= m_rEngine
.GetText(nNumber
).Len())
1032 throw ::css::lang::IndexOutOfBoundsException(
1034 RTL_CONSTASCII_USTRINGPARAM(
1035 "textwindowaccessibility.cxx:"
1036 " Document::retrieveCharacterAttributes")),
1037 static_cast< ::css::uno::XWeak
* >(this));
1039 // retrieve default attributes
1040 tPropValMap aCharAttrSeq
;
1041 retrieveDefaultAttributesImpl( pParagraph
, aRequestedAttributes
, aCharAttrSeq
);
1043 // retrieve run attributes
1044 tPropValMap aRunAttrSeq
;
1045 retrieveRunAttributesImpl( pParagraph
, nIndex
, aRequestedAttributes
, aRunAttrSeq
);
1047 // merge default and run attributes
1048 for ( tPropValMap::const_iterator aRunIter
= aRunAttrSeq
.begin();
1049 aRunIter
!= aRunAttrSeq
.end();
1052 aCharAttrSeq
[ aRunIter
->first
] = aRunIter
->second
;
1055 return convertHashMapToSequence( aCharAttrSeq
);
1058 void Document::retrieveDefaultAttributesImpl(
1059 ParagraphImpl
const * pParagraph
,
1060 const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
,
1061 tPropValMap
& rDefAttrSeq
)
1063 // default attributes are not supported by text engine
1065 (void) RequestedAttributes
;
1069 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1070 Document::retrieveDefaultAttributes(
1071 ParagraphImpl
const * pParagraph
,
1072 const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
)
1074 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1075 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1077 tPropValMap aDefAttrSeq
;
1078 retrieveDefaultAttributesImpl( pParagraph
, RequestedAttributes
, aDefAttrSeq
);
1079 return convertHashMapToSequence( aDefAttrSeq
);
1083 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1084 Document::convertHashMapToSequence(tPropValMap
& rAttrSeq
)
1086 ::css::uno::Sequence
< ::css::beans::PropertyValue
> aValues( rAttrSeq
.size() );
1087 ::css::beans::PropertyValue
* pValues
= aValues
.getArray();
1089 for ( tPropValMap::const_iterator aIter
= rAttrSeq
.begin();
1090 aIter
!= rAttrSeq
.end();
1093 pValues
[i
] = aIter
->second
;
1099 void Document::retrieveRunAttributesImpl(
1100 ParagraphImpl
const * pParagraph
, ::sal_Int32 Index
,
1101 const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
,
1102 tPropValMap
& rRunAttrSeq
)
1104 ::ULONG nNumber
= static_cast< ::ULONG
>( pParagraph
->getNumber() );
1105 ::TextPaM
aPaM( nNumber
, static_cast< ::USHORT
>( Index
) );
1106 // XXX numeric overflow
1107 // FIXME TEXTATTR_HYPERLINK ignored:
1108 ::TextAttribFontColor
const * pColor
1109 = static_cast< ::TextAttribFontColor
const * >(
1110 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTCOLOR
) );
1111 ::TextAttribFontWeight
const * pWeight
1112 = static_cast< ::TextAttribFontWeight
const * >(
1113 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTWEIGHT
) );
1114 tPropValMap aRunAttrSeq
;
1117 ::css::beans::PropertyValue aPropVal
;
1119 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharColor" ) );
1120 aPropVal
.Handle
= -1;
1121 aPropVal
.Value
= mapFontColor( pColor
->GetColor() );
1122 aPropVal
.State
= ::css::beans::PropertyState_DIRECT_VALUE
;
1123 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1127 ::css::beans::PropertyValue aPropVal
;
1129 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "CharWeight" ) );
1130 aPropVal
.Handle
= -1;
1131 aPropVal
.Value
= mapFontWeight( pWeight
->getFontWeight() );
1132 aPropVal
.State
= ::css::beans::PropertyState_DIRECT_VALUE
;
1133 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1135 if ( RequestedAttributes
.getLength() == 0 )
1137 rRunAttrSeq
= aRunAttrSeq
;
1141 const ::rtl::OUString
* pReqAttrs
= RequestedAttributes
.getConstArray();
1142 const ::sal_Int32 nLength
= RequestedAttributes
.getLength();
1143 for ( ::sal_Int32 i
= 0; i
< nLength
; ++i
)
1145 tPropValMap::iterator aIter
= aRunAttrSeq
.find( pReqAttrs
[i
] );
1146 if ( aIter
!= aRunAttrSeq
.end() )
1148 rRunAttrSeq
[ (*aIter
).first
] = (*aIter
).second
;
1154 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1155 Document::retrieveRunAttributes(
1156 ParagraphImpl
const * pParagraph
, ::sal_Int32 Index
,
1157 const ::css::uno::Sequence
< ::rtl::OUString
>& RequestedAttributes
)
1159 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1160 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1161 ::ULONG nNumber
= static_cast< ::ULONG
>( pParagraph
->getNumber() );
1162 // XXX numeric overflow
1163 if ( Index
< 0 || Index
>= m_rEngine
.GetText(nNumber
).Len() )
1164 throw ::css::lang::IndexOutOfBoundsException(
1166 RTL_CONSTASCII_USTRINGPARAM(
1167 "textwindowaccessibility.cxx:"
1168 " Document::retrieveRunAttributes") ),
1169 static_cast< ::css::uno::XWeak
* >( this ) );
1171 tPropValMap aRunAttrSeq
;
1172 retrieveRunAttributesImpl( pParagraph
, Index
, RequestedAttributes
, aRunAttrSeq
);
1173 return convertHashMapToSequence( aRunAttrSeq
);
1176 void Document::changeParagraphText(ParagraphImpl
* pParagraph
,
1177 ::rtl::OUString
const & rText
)
1179 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1181 ::osl::MutexGuard
aInternalGuard(GetMutex());
1182 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1183 // XXX numeric overflow
1184 changeParagraphText(nNumber
, 0, m_rEngine
.GetTextLen(nNumber
), false,
1189 void Document::changeParagraphText(ParagraphImpl
* pParagraph
,
1190 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1191 bool bCut
, bool bPaste
,
1192 ::rtl::OUString
const & rText
)
1194 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1196 ::osl::MutexGuard
aInternalGuard(GetMutex());
1197 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1198 // XXX numeric overflow
1199 if (nBegin
< 0 || nBegin
> nEnd
1200 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1201 throw ::css::lang::IndexOutOfBoundsException(
1203 RTL_CONSTASCII_USTRINGPARAM(
1204 "textwindowaccessibility.cxx:"
1205 " Document::changeParagraphText")),
1206 static_cast< ::css::uno::XWeak
* >(this));
1207 changeParagraphText(nNumber
, static_cast< ::USHORT
>(nBegin
),
1208 static_cast< ::USHORT
>(nEnd
), bCut
, bPaste
, rText
);
1209 // XXX numeric overflow (2x)
1213 void Document::copyParagraphText(ParagraphImpl
const * pParagraph
,
1214 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1216 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1218 ::osl::MutexGuard
aInternalGuard(GetMutex());
1219 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1220 // XXX numeric overflow
1221 if (nBegin
< 0 || nBegin
> nEnd
1222 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1223 throw ::css::lang::IndexOutOfBoundsException(
1224 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1225 "textwindowaccessibility.cxx:"
1226 " Document::copyParagraphText")),
1227 static_cast< ::css::uno::XWeak
* >(this));
1228 m_rView
.SetSelection(
1229 ::TextSelection(::TextPaM(nNumber
, static_cast< ::USHORT
>(nBegin
)),
1230 ::TextPaM(nNumber
, static_cast< ::USHORT
>(nEnd
))));
1231 // XXX numeric overflow (2x)
1236 void Document::changeParagraphAttributes(
1237 ParagraphImpl
* pParagraph
, ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1238 ::css::uno::Sequence
< ::css::beans::PropertyValue
> const & rAttributeSet
)
1240 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1242 ::osl::MutexGuard
aInternalGuard(GetMutex());
1243 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1244 // XXX numeric overflow
1245 if (nBegin
< 0 || nBegin
> nEnd
1246 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1247 throw ::css::lang::IndexOutOfBoundsException(
1249 RTL_CONSTASCII_USTRINGPARAM(
1250 "textwindowaccessibility.cxx:"
1251 " Document::changeParagraphAttributes")),
1252 static_cast< ::css::uno::XWeak
* >(this));
1254 // FIXME The new attributes are added to any attributes already set,
1255 // they do not replace the old attributes as required by
1256 // XAccessibleEditableText.setAttributes:
1257 for (::sal_Int32 i
= 0; i
< rAttributeSet
.getLength(); ++i
)
1258 if (rAttributeSet
[i
].Name
.equalsAsciiL(
1259 RTL_CONSTASCII_STRINGPARAM("CharColor")))
1260 m_rEngine
.SetAttrib(::TextAttribFontColor(
1261 mapFontColor(rAttributeSet
[i
].Value
)),
1262 nNumber
, static_cast< ::USHORT
>(nBegin
),
1263 static_cast< ::USHORT
>(nEnd
));
1264 // XXX numeric overflow (2x)
1265 else if (rAttributeSet
[i
].Name
.equalsAsciiL(
1266 RTL_CONSTASCII_STRINGPARAM("CharWeight")))
1267 m_rEngine
.SetAttrib(::TextAttribFontWeight(
1268 mapFontWeight(rAttributeSet
[i
].Value
)),
1269 nNumber
, static_cast< ::USHORT
>(nBegin
),
1270 static_cast< ::USHORT
>(nEnd
));
1271 // XXX numeric overflow (2x)
1275 void Document::changeParagraphSelection(ParagraphImpl
* pParagraph
,
1276 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1278 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1280 ::osl::MutexGuard
aInternalGuard(GetMutex());
1281 ::ULONG nNumber
= static_cast< ::ULONG
>(pParagraph
->getNumber());
1282 // XXX numeric overflow
1283 if (nBegin
< 0 || nBegin
> nEnd
1284 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1285 throw ::css::lang::IndexOutOfBoundsException(
1286 ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
1287 "textwindowaccessibility.cxx:"
1288 " Document::changeParagraphSelection")),
1289 static_cast< ::css::uno::XWeak
* >(this));
1290 m_rView
.SetSelection(
1291 ::TextSelection(::TextPaM(nNumber
, static_cast< ::USHORT
>(nBegin
)),
1292 ::TextPaM(nNumber
, static_cast< ::USHORT
>(nEnd
))));
1293 // XXX numeric overflow (2x)
1297 ::css::i18n::Boundary
1298 Document::retrieveParagraphLineBoundary( ParagraphImpl
const * pParagraph
,
1299 ::sal_Int32 nIndex
, ::sal_Int32
*pLineNo
)
1301 ::css::i18n::Boundary aBoundary
;
1302 aBoundary
.startPos
= nIndex
;
1303 aBoundary
.endPos
= nIndex
;
1305 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1307 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1308 ::ULONG nNumber
= static_cast< ::ULONG
>( pParagraph
->getNumber() );
1309 if ( nIndex
< 0 || nIndex
> m_rEngine
.GetText( nNumber
).Len() )
1310 throw ::css::lang::IndexOutOfBoundsException(
1312 RTL_CONSTASCII_USTRINGPARAM(
1313 "textwindowaccessibility.cxx:"
1314 " Document::retrieveParagraphLineBoundary" ) ),
1315 static_cast< ::css::uno::XWeak
* >( this ) );
1316 ::sal_Int32 nLineStart
= 0;
1317 ::sal_Int32 nLineEnd
= 0;
1318 ::USHORT nLineCount
= m_rEngine
.GetLineCount( nNumber
);
1319 for ( ::USHORT nLine
= 0; nLine
< nLineCount
; ++nLine
)
1321 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1322 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1323 nLineStart
= nLineEnd
;
1324 nLineEnd
+= nLineLength
;
1325 if ( nIndex
>= nLineStart
&& ( ( nLine
== nLineCount
- 1 ) ? nIndex
<= nLineEnd
: nIndex
< nLineEnd
) )
1327 aBoundary
.startPos
= nLineStart
;
1328 aBoundary
.endPos
= nLineEnd
;
1339 ::css::i18n::Boundary
1340 Document::retrieveParagraphBoundaryOfLine( ParagraphImpl
const * pParagraph
,
1341 ::sal_Int32 nLineNo
)
1343 ::css::i18n::Boundary aBoundary
;
1344 aBoundary
.startPos
= 0;
1345 aBoundary
.endPos
= 0;
1347 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1349 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1350 ::ULONG nNumber
= static_cast< ::ULONG
>( pParagraph
->getNumber() );
1351 if ( nLineNo
>= m_rEngine
.GetLineCount( nNumber
) )
1352 throw ::css::lang::IndexOutOfBoundsException(
1354 RTL_CONSTASCII_USTRINGPARAM(
1355 "textwindowaccessibility.cxx:"
1356 " Document::retrieveParagraphBoundaryOfLine" ) ),
1357 static_cast< ::css::uno::XWeak
* >( this ) );
1358 ::sal_Int32 nLineStart
= 0;
1359 ::sal_Int32 nLineEnd
= 0;
1360 for ( ::USHORT nLine
= 0; nLine
<= nLineNo
; ++nLine
)
1362 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1363 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1364 nLineStart
= nLineEnd
;
1365 nLineEnd
+= nLineLength
;
1368 aBoundary
.startPos
= nLineStart
;
1369 aBoundary
.endPos
= nLineEnd
;
1375 sal_Int32
Document::retrieveParagraphLineWithCursor( ParagraphImpl
const * pParagraph
)
1377 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1378 ::osl::MutexGuard
aInternalGuard(GetMutex());
1379 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
1380 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
1381 TextPaM
aEndPaM( rSelection
.GetEnd() );
1383 return aEndPaM
.GetPara() == nNumber
1384 ? m_rView
.GetLineNumberOfCursorInSelection() : -1;
1388 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
>
1389 Document::retrieveParagraphRelationSet( ParagraphImpl
const * pParagraph
)
1391 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1393 ::utl::AccessibleRelationSetHelper
* pRelationSetHelper
= new ::utl::AccessibleRelationSetHelper();
1394 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
> xSet
= pRelationSetHelper
;
1396 Paragraphs::iterator
aPara( m_xParagraphs
->begin() + pParagraph
->getNumber() );
1398 if ( aPara
> m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
1400 ::css::uno::Sequence
< ::css::uno::Reference
< ::css::uno::XInterface
> > aSequence(1);
1401 aSequence
[0] = getAccessibleChild( aPara
- 1 );
1402 ::css::accessibility::AccessibleRelation
aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM
, aSequence
);
1403 pRelationSetHelper
->AddRelation( aRelation
);
1406 if ( aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
-1 )
1408 ::css::uno::Sequence
< ::css::uno::Reference
< ::css::uno::XInterface
> > aSequence(1);
1409 aSequence
[0] = getAccessibleChild( aPara
+ 1 );
1410 ::css::accessibility::AccessibleRelation
aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO
, aSequence
);
1411 pRelationSetHelper
->AddRelation( aRelation
);
1417 void Document::ProcessWindowEvent( const VclWindowEvent
& rVclWindowEvent
)
1419 switch ( rVclWindowEvent
.GetId() )
1421 case VCLEVENT_WINDOW_GETFOCUS
:
1422 case VCLEVENT_WINDOW_LOSEFOCUS
:
1424 // #107179# if our parent is a compound control (e.g. MultiLineEdit),
1425 // suppress the window focus events here
1426 if ( !m_bCompoundControlChild
)
1427 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent
);
1431 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent
);
1436 ::sal_Int32 SAL_CALL
Document::getAccessibleChildCount()
1437 throw (::css::uno::RuntimeException
)
1439 ::comphelper::OExternalLockGuard
aGuard(this);
1441 return m_aVisibleEnd
- m_aVisibleBegin
;
1445 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
1446 Document::getAccessibleChild(::sal_Int32 i
)
1447 throw (::css::lang::IndexOutOfBoundsException
,
1448 ::css::uno::RuntimeException
)
1450 ::comphelper::OExternalLockGuard
aGuard(this);
1452 if (i
< 0 || i
>= m_aVisibleEnd
- m_aVisibleBegin
)
1453 throw ::css::lang::IndexOutOfBoundsException(
1455 RTL_CONSTASCII_USTRINGPARAM(
1456 "textwindowaccessibility.cxx:"
1457 " Document::getAccessibleChild")),
1458 static_cast< ::css::uno::XWeak
* >(this));
1459 return getAccessibleChild(m_aVisibleBegin
1460 + static_cast< Paragraphs::size_type
>(i
));
1464 ::sal_Int16 SAL_CALL
Document::getAccessibleRole()
1465 throw (::css::uno::RuntimeException
)
1467 return ::css::accessibility::AccessibleRole::TEXT_FRAME
;
1471 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
1472 Document::getAccessibleAtPoint(::css::awt::Point
const & rPoint
)
1473 throw (::css::uno::RuntimeException
)
1475 ::comphelper::OExternalLockGuard
aGuard(this);
1478 && rPoint
.X
< m_rView
.GetWindow()->GetOutputSizePixel().Width()
1479 && rPoint
.Y
>= 0 && rPoint
.Y
< m_nViewHeight
)
1481 ::sal_Int32 nOffset
= m_nViewOffset
+ rPoint
.Y
; // XXX numeric overflow
1482 ::sal_Int32 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
1483 for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1486 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1488 return getAccessibleChild(aIt
);
1495 void SAL_CALL
Document::disposing()
1497 m_aEngineListener
.endListening();
1498 m_aViewListener
.endListening();
1499 if (m_xParagraphs
.get() != 0)
1500 disposeParagraphs();
1501 VCLXAccessibleComponent::disposing();
1505 void Document::Notify(::SfxBroadcaster
&, ::SfxHint
const & rHint
)
1507 if (rHint
.ISA(::TextHint
))
1509 ::TextHint
const & rTextHint
1510 = static_cast< ::TextHint
const & >(rHint
);
1511 switch (rTextHint
.GetId())
1513 case TEXT_HINT_PARAINSERTED
:
1514 case TEXT_HINT_PARAREMOVED
:
1515 // TEXT_HINT_PARAINSERTED and TEXT_HINT_PARAREMOVED are sent at
1516 // "unsafe" times (when the text engine has not yet re-formatted its
1517 // content), so that for example calling ::TextEngine::GetTextHeight
1518 // from within the code that handles TEXT_HINT_PARAINSERTED causes
1519 // trouble within the text engine. Therefore, these hints are just
1520 // buffered until a following ::TextEngine::FormatDoc causes a
1521 // TEXT_HINT_TEXTFORMATTED to come in:
1522 case TEXT_HINT_FORMATPARA
:
1523 // ::TextEngine::FormatDoc sends a sequence of
1524 // TEXT_HINT_FORMATPARAs, followed by an optional
1525 // TEXT_HINT_TEXTHEIGHTCHANGED, followed in all cases by one
1526 // TEXT_HINT_TEXTFORMATTED. Only the TEXT_HINT_FORMATPARAs contain
1527 // the the numbers of the affected paragraphs, but they are sent
1528 // before the changes are applied. Therefore, TEXT_HINT_FORMATPARAs
1529 // are just buffered until another hint comes in:
1531 ::osl::MutexGuard
aInternalGuard(GetMutex());
1535 m_aParagraphNotifications
.push(rTextHint
);
1538 case TEXT_HINT_TEXTFORMATTED
:
1539 case TEXT_HINT_TEXTHEIGHTCHANGED
:
1540 case TEXT_HINT_MODIFIED
:
1542 ::osl::MutexGuard
aInternalGuard(GetMutex());
1545 handleParagraphNotifications();
1548 case TEXT_HINT_VIEWSCROLLED
:
1550 ::osl::MutexGuard
aInternalGuard(GetMutex());
1553 handleParagraphNotifications();
1555 ::sal_Int32 nOffset
= static_cast< ::sal_Int32
>(
1556 m_rView
.GetStartDocPos().Y());
1557 // XXX numeric overflow
1558 if (nOffset
!= m_nViewOffset
)
1560 m_nViewOffset
= nOffset
;
1562 Paragraphs::iterator
aOldVisibleBegin(
1564 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1566 determineVisibleRange();
1568 notifyVisibleRangeChanges(aOldVisibleBegin
,
1570 m_xParagraphs
->end());
1574 case TEXT_HINT_VIEWSELECTIONCHANGED
:
1576 ::osl::MutexGuard
aInternalGuard(GetMutex());
1580 if (m_aParagraphNotifications
.empty())
1582 handleSelectionChangeNotification();
1586 // TEXT_HINT_VIEWSELECTIONCHANGED is sometimes sent at
1587 // "unsafe" times (when the text engine has not yet re-
1588 // formatted its content), so that for example calling
1589 // ::TextEngine::GetTextHeight from within the code that
1590 // handles a previous TEXT_HINT_PARAINSERTED causes
1591 // trouble within the text engine. Therefore, these
1592 // hints are just buffered (along with
1593 // TEXT_HINT_PARAINSERTED/REMOVED/FORMATPARA) until a
1594 // following ::TextEngine::FormatDoc causes a
1595 // TEXT_HINT_TEXTFORMATTED to come in:
1596 m_bSelectionChangedNotification
= true;
1604 IMPL_LINK(Document
, WindowEventHandler
, ::VclSimpleEvent
*, pEvent
)
1606 switch (pEvent
->GetId())
1608 case VCLEVENT_WINDOW_RESIZE
:
1610 ::osl::MutexGuard
aInternalGuard(GetMutex());
1614 ::sal_Int32 nHeight
= static_cast< ::sal_Int32
>(
1615 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1616 // XXX numeric overflow
1617 if (nHeight
!= m_nViewHeight
)
1619 m_nViewHeight
= nHeight
;
1621 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
1622 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1624 determineVisibleRange();
1626 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
1627 m_xParagraphs
->end());
1631 case VCLEVENT_WINDOW_GETFOCUS
:
1633 ::osl::MutexGuard
aInternalGuard(GetMutex());
1637 if (m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
1639 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1640 getParagraph(m_aFocused
));
1641 if (xParagraph
.is())
1642 xParagraph
->notifyEvent(
1643 ::css::accessibility::AccessibleEventId::
1646 ::css::uno::makeAny(
1647 ::css::accessibility::AccessibleStateType::
1652 case VCLEVENT_WINDOW_LOSEFOCUS
:
1654 ::osl::MutexGuard
aInternalGuard(GetMutex());
1658 if (m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
1660 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1661 getParagraph(m_aFocused
));
1662 if (xParagraph
.is())
1663 xParagraph
->notifyEvent(
1664 ::css::accessibility::AccessibleEventId::
1666 ::css::uno::makeAny(
1667 ::css::accessibility::AccessibleStateType::
1677 void Document::init()
1679 if (m_xParagraphs
.get() == 0)
1681 ::ULONG nCount
= m_rEngine
.GetParagraphCount();
1682 ::std::auto_ptr
< Paragraphs
> p(new Paragraphs
);
1683 p
->reserve(static_cast< Paragraphs::size_type
>(nCount
));
1684 // numeric overflow is harmless here
1685 for (::ULONG i
= 0; i
< nCount
; ++i
)
1686 p
->push_back(ParagraphInfo(static_cast< ::sal_Int32
>(
1687 m_rEngine
.GetTextHeight(i
))));
1688 // XXX numeric overflow
1689 m_nViewOffset
= static_cast< ::sal_Int32
>(
1690 m_rView
.GetStartDocPos().Y()); // XXX numeric overflow
1691 m_nViewHeight
= static_cast< ::sal_Int32
>(
1692 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1693 // XXX numeric overflow
1695 determineVisibleRange();
1696 m_nSelectionFirstPara
= -1;
1697 m_nSelectionFirstPos
= -1;
1698 m_nSelectionLastPara
= -1;
1699 m_nSelectionLastPos
= -1;
1700 m_aFocused
= m_xParagraphs
->end();
1701 m_bSelectionChangedNotification
= false;
1702 m_aEngineListener
.startListening(m_rEngine
);
1703 m_aViewListener
.startListening(*m_rView
.GetWindow());
1707 ::rtl::Reference
< ParagraphImpl
>
1708 Document::getParagraph(Paragraphs::iterator
const & rIt
)
1710 return static_cast< ParagraphImpl
* >(
1711 ::css::uno::Reference
< ::css::accessibility::XAccessible
>(
1712 rIt
->getParagraph()).get());
1715 ::css::uno::Reference
< ::css::accessibility::XAccessible
>
1716 Document::getAccessibleChild(Paragraphs::iterator
const & rIt
)
1718 ::css::uno::Reference
< ::css::accessibility::XAccessible
> xParagraph(
1719 rIt
->getParagraph());
1720 if (!xParagraph
.is())
1722 xParagraph
= new Paragraph(this, rIt
- m_xParagraphs
->begin());
1723 rIt
->setParagraph(xParagraph
);
1728 void Document::determineVisibleRange()
1730 m_aVisibleBegin
= m_xParagraphs
->end();
1731 m_aVisibleEnd
= m_aVisibleBegin
;
1732 ::sal_Int32 nPos
= 0;
1733 for (Paragraphs::iterator aIt
= m_xParagraphs
->begin();;)
1735 if (aIt
== m_xParagraphs
->end())
1737 m_nVisibleBeginOffset
= 0;
1740 ::sal_Int32 nOldPos
= nPos
;
1741 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1742 if (m_aVisibleBegin
== m_xParagraphs
->end() && nPos
>= m_nViewOffset
)
1744 m_aVisibleBegin
= aIt
;
1745 m_nVisibleBeginOffset
= m_nViewOffset
- nOldPos
;
1748 if (m_aVisibleBegin
!= m_xParagraphs
->end()
1749 && (aIt
== m_xParagraphs
->end()
1750 || nPos
>= m_nViewOffset
+ m_nViewHeight
))
1751 // XXX numeric overflow
1753 m_aVisibleEnd
= aIt
;
1759 void Document::notifyVisibleRangeChanges(
1760 Paragraphs::iterator
const & rOldVisibleBegin
,
1761 Paragraphs::iterator
const & rOldVisibleEnd
,
1762 Paragraphs::iterator
const & rInserted
)
1764 // XXX Replace this code that determines which paragraphs have changed from
1765 // invisible to visible or vice versa with a better algorithm.
1766 {for (Paragraphs::iterator
aIt(rOldVisibleBegin
); aIt
!= rOldVisibleEnd
;
1768 if (aIt
!= rInserted
1769 && (aIt
< m_aVisibleBegin
|| aIt
>= m_aVisibleEnd
))
1770 NotifyAccessibleEvent(
1771 ::css::accessibility::AccessibleEventId::
1773 ::css::uno::makeAny(getAccessibleChild(aIt
)),
1776 {for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1778 if (aIt
== rInserted
1779 || aIt
< rOldVisibleBegin
|| aIt
>= rOldVisibleEnd
)
1780 NotifyAccessibleEvent(
1781 ::css::accessibility::AccessibleEventId::
1784 ::css::uno::makeAny(getAccessibleChild(aIt
)));
1789 Document::changeParagraphText(::ULONG nNumber
, ::USHORT nBegin
, ::USHORT nEnd
,
1790 bool bCut
, bool bPaste
,
1791 ::rtl::OUString
const & rText
)
1793 m_rView
.SetSelection(::TextSelection(::TextPaM(nNumber
, nBegin
),
1794 ::TextPaM(nNumber
, nEnd
)));
1797 else if (nBegin
!= nEnd
)
1798 m_rView
.DeleteSelected();
1801 else if (rText
.getLength() != 0)
1802 m_rView
.InsertText(rText
);
1805 void Document::handleParagraphNotifications()
1807 while (!m_aParagraphNotifications
.empty())
1809 ::TextHint
aHint(m_aParagraphNotifications
.front());
1810 m_aParagraphNotifications
.pop();
1811 switch (aHint
.GetId())
1813 case TEXT_HINT_PARAINSERTED
:
1815 ::ULONG n
= aHint
.GetValue();
1816 OSL_ENSURE(n
<= m_xParagraphs
->size(),
1817 "bad TEXT_HINT_PARAINSERTED event");
1819 // Save the values of old iterators (the iterators themselves
1820 // will get invalidated), and adjust the old values so that they
1821 // reflect the insertion of the new paragraph:
1822 Paragraphs::size_type nOldVisibleBegin
1823 = m_aVisibleBegin
- m_xParagraphs
->begin();
1824 Paragraphs::size_type nOldVisibleEnd
1825 = m_aVisibleEnd
- m_xParagraphs
->begin();
1826 Paragraphs::size_type nOldFocused
1827 = m_aFocused
- m_xParagraphs
->begin();
1828 if (n
<= nOldVisibleBegin
)
1829 ++nOldVisibleBegin
; // XXX numeric overflow
1830 if (n
<= nOldVisibleEnd
)
1831 ++nOldVisibleEnd
; // XXX numeric overflow
1832 if (n
<= nOldFocused
)
1833 ++nOldFocused
; // XXX numeric overflow
1834 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionFirstPara
)
1835 ++m_nSelectionFirstPara
; // XXX numeric overflow
1836 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionLastPara
)
1837 ++m_nSelectionLastPara
; // XXX numeric overflow
1839 Paragraphs::iterator
aIns(
1840 m_xParagraphs
->insert(
1841 m_xParagraphs
->begin() + n
,
1842 ParagraphInfo(static_cast< ::sal_Int32
>(
1843 m_rEngine
.GetTextHeight(n
)))));
1844 // XXX numeric overflow (2x)
1846 determineVisibleRange();
1847 m_aFocused
= m_xParagraphs
->begin() + nOldFocused
;
1849 for (Paragraphs::iterator
aIt(aIns
);;)
1852 if (aIt
== m_xParagraphs
->end())
1854 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1856 if (xParagraph
.is())
1857 xParagraph
->numberChanged(true);
1860 notifyVisibleRangeChanges(
1861 m_xParagraphs
->begin() + nOldVisibleBegin
,
1862 m_xParagraphs
->begin() + nOldVisibleEnd
, aIns
);
1865 case TEXT_HINT_PARAREMOVED
:
1867 ::ULONG n
= aHint
.GetValue();
1868 if (n
== TEXT_PARA_ALL
)
1870 {for (Paragraphs::iterator
aIt(m_aVisibleBegin
);
1871 aIt
!= m_aVisibleEnd
; ++aIt
)
1872 NotifyAccessibleEvent(
1873 ::css::accessibility::AccessibleEventId::
1875 ::css::uno::makeAny(getAccessibleChild(aIt
)),
1878 disposeParagraphs();
1879 m_xParagraphs
->clear();
1880 determineVisibleRange();
1881 m_nSelectionFirstPara
= -1;
1882 m_nSelectionFirstPos
= -1;
1883 m_nSelectionLastPara
= -1;
1884 m_nSelectionLastPos
= -1;
1885 m_aFocused
= m_xParagraphs
->end();
1889 OSL_ENSURE(n
< m_xParagraphs
->size(),
1890 "Bad TEXT_HINT_PARAREMOVED event");
1892 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
1893 // numeric overflow cannot occur
1895 // Save the values of old iterators (the iterators
1896 // themselves will get invalidated), and adjust the old
1897 // values so that they reflect the removal of the paragraph:
1898 Paragraphs::size_type nOldVisibleBegin
1899 = m_aVisibleBegin
- m_xParagraphs
->begin();
1900 Paragraphs::size_type nOldVisibleEnd
1901 = m_aVisibleEnd
- m_xParagraphs
->begin();
1903 = nOldVisibleBegin
<= n
&& n
< nOldVisibleEnd
;
1904 Paragraphs::size_type nOldFocused
1905 = m_aFocused
- m_xParagraphs
->begin();
1906 bool bWasFocused
= aIt
== m_aFocused
;
1907 if (n
< nOldVisibleBegin
)
1909 if (n
< nOldVisibleEnd
)
1911 if (n
< nOldFocused
)
1913 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionFirstPara
)
1914 --m_nSelectionFirstPara
;
1915 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionFirstPara
)
1917 if (m_nSelectionFirstPara
== m_nSelectionLastPara
)
1919 m_nSelectionFirstPara
= -1;
1920 m_nSelectionFirstPos
= -1;
1921 m_nSelectionLastPara
= -1;
1922 m_nSelectionLastPos
= -1;
1926 ++m_nSelectionFirstPara
;
1927 m_nSelectionFirstPos
= 0;
1930 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionLastPara
)
1931 --m_nSelectionLastPara
;
1932 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionLastPara
)
1934 OSL_ENSURE(m_nSelectionFirstPara
< m_nSelectionLastPara
,
1936 --m_nSelectionLastPara
;
1937 m_nSelectionLastPos
= 0x7FFFFFFF;
1940 ::css::uno::Reference
< ::css::accessibility::XAccessible
>
1943 xStrong
= getAccessibleChild(aIt
);
1944 ::css::uno::WeakReference
<
1945 ::css::accessibility::XAccessible
> xWeak(
1946 aIt
->getParagraph());
1947 aIt
= m_xParagraphs
->erase(aIt
);
1949 determineVisibleRange();
1950 m_aFocused
= bWasFocused
? m_xParagraphs
->end()
1951 : m_xParagraphs
->begin() + nOldFocused
;
1953 for (; aIt
!= m_xParagraphs
->end(); ++aIt
)
1955 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1957 if (xParagraph
.is())
1958 xParagraph
->numberChanged(false);
1962 NotifyAccessibleEvent(
1963 ::css::accessibility::AccessibleEventId::
1965 ::css::uno::makeAny(getAccessibleChild(aIt
)),
1968 ::css::uno::Reference
< ::css::lang::XComponent
> xComponent(
1969 xWeak
.get(), ::css::uno::UNO_QUERY
);
1970 if (xComponent
.is())
1971 xComponent
->dispose();
1973 notifyVisibleRangeChanges(
1974 m_xParagraphs
->begin() + nOldVisibleBegin
,
1975 m_xParagraphs
->begin() + nOldVisibleEnd
,
1976 m_xParagraphs
->end());
1980 case TEXT_HINT_FORMATPARA
:
1982 ::ULONG n
= aHint
.GetValue();
1983 OSL_ENSURE(n
< m_xParagraphs
->size(),
1984 "Bad TEXT_HINT_FORMATPARA event");
1986 (*m_xParagraphs
)[static_cast< Paragraphs::size_type
>(n
)].
1987 changeHeight(static_cast< ::sal_Int32
>(
1988 m_rEngine
.GetTextHeight(n
)));
1989 // XXX numeric overflow
1990 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
1991 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1992 determineVisibleRange();
1993 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
1994 m_xParagraphs
->end());
1995 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
1996 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(aIt
));
1997 if (xParagraph
.is())
1998 xParagraph
->textChanged();
2002 OSL_ENSURE(false, "bad buffered hint");
2006 if (m_bSelectionChangedNotification
)
2008 m_bSelectionChangedNotification
= false;
2009 handleSelectionChangeNotification();
2013 void Document::handleSelectionChangeNotification()
2015 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
2016 OSL_ENSURE(rSelection
.GetStart().GetPara() < m_xParagraphs
->size()
2017 && rSelection
.GetEnd().GetPara() < m_xParagraphs
->size(),
2018 "bad TEXT_HINT_VIEWSELECTIONCHANGED event");
2019 ::sal_Int32 nNewFirstPara
2020 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetPara());
2021 ::sal_Int32 nNewFirstPos
2022 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetIndex());
2023 // XXX numeric overflow
2024 ::sal_Int32 nNewLastPara
2025 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetPara());
2026 ::sal_Int32 nNewLastPos
2027 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetIndex());
2028 // XXX numeric overflow
2031 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + nNewLastPara
);
2032 if (m_aFocused
!= m_xParagraphs
->end() && m_aFocused
!= aIt
2033 && m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
2035 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(m_aFocused
));
2036 if (xParagraph
.is())
2037 xParagraph
->notifyEvent(
2038 ::css::accessibility::AccessibleEventId::
2040 ::css::uno::makeAny(
2041 ::css::accessibility::AccessibleStateType::FOCUSED
),
2045 // Gain focus and update cursor position:
2046 if (aIt
>= m_aVisibleBegin
&& aIt
< m_aVisibleEnd
2047 && (aIt
!= m_aFocused
2048 || nNewLastPara
!= m_nSelectionLastPara
2049 || nNewLastPos
!= m_nSelectionLastPos
))
2051 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(aIt
));
2052 if (xParagraph
.is())
2054 if (aIt
!= m_aFocused
)
2055 xParagraph
->notifyEvent(
2056 ::css::accessibility::AccessibleEventId::
2059 ::css::uno::makeAny(
2060 ::css::accessibility::AccessibleStateType::FOCUSED
));
2061 if (nNewLastPara
!= m_nSelectionLastPara
2062 || nNewLastPos
!= m_nSelectionLastPos
)
2063 xParagraph
->notifyEvent(
2064 ::css::accessibility::AccessibleEventId::
2066 ::css::uno::makeAny
< ::sal_Int32
>(
2067 nNewLastPara
== m_nSelectionLastPara
2068 ? m_nSelectionLastPos
: 0),
2069 ::css::uno::makeAny(nNewLastPos
));
2074 // Update both old and new selection. (Regardless of how the two selections
2075 // look like, there will always be two ranges to the left and right of the
2076 // overlap---the overlap and/or the range to the right of it possibly being
2077 // empty. Only for these two ranges notifications have to be sent.)
2079 TextPaM
aOldTextStart( static_cast< ULONG
>( m_nSelectionFirstPara
), static_cast< USHORT
>( m_nSelectionFirstPos
) );
2080 TextPaM
aOldTextEnd( static_cast< ULONG
>( m_nSelectionLastPara
), static_cast< USHORT
>( m_nSelectionLastPos
) );
2081 TextPaM
aNewTextStart( static_cast< ULONG
>( nNewFirstPara
), static_cast< USHORT
>( nNewFirstPos
) );
2082 TextPaM
aNewTextEnd( static_cast< ULONG
>( nNewLastPara
), static_cast< USHORT
>( nNewLastPos
) );
2084 // justify selections
2085 justifySelection( aOldTextStart
, aOldTextEnd
);
2086 justifySelection( aNewTextStart
, aNewTextEnd
);
2093 if ( m_nSelectionFirstPara
== -1 )
2095 // old selection not initialized yet => notify events only for new selection (if not empty)
2096 nFirst1
= aNewTextStart
.GetPara();
2097 nLast1
= aNewTextEnd
.GetPara() + ( aNewTextStart
!= aNewTextEnd
? 1 : 0 );
2101 else if ( aOldTextStart
== aOldTextEnd
&& aNewTextStart
== aNewTextEnd
)
2103 // old an new selection empty => no events
2109 else if ( aOldTextStart
!= aOldTextEnd
&& aNewTextStart
== aNewTextEnd
)
2111 // old selection not empty + new selection empty => notify events only for old selection
2112 nFirst1
= aOldTextStart
.GetPara();
2113 nLast1
= aOldTextEnd
.GetPara() + 1;
2117 else if ( aOldTextStart
== aOldTextEnd
&& aNewTextStart
!= aNewTextEnd
)
2119 // old selection empty + new selection not empty => notify events only for new selection
2120 nFirst1
= aNewTextStart
.GetPara();
2121 nLast1
= aNewTextEnd
.GetPara() + 1;
2127 // old and new selection not empty => notify events for the two ranges left and right of the overlap
2128 ::std::vector
< TextPaM
> aTextPaMs(4);
2129 aTextPaMs
[0] = aOldTextStart
;
2130 aTextPaMs
[1] = aOldTextEnd
;
2131 aTextPaMs
[2] = aNewTextStart
;
2132 aTextPaMs
[3] = aNewTextEnd
;
2133 ::std::sort( aTextPaMs
.begin(), aTextPaMs
.end() );
2135 nFirst1
= aTextPaMs
[0].GetPara();
2136 nLast1
= aTextPaMs
[1].GetPara() + ( aTextPaMs
[0] != aTextPaMs
[1] ? 1 : 0 );
2138 nFirst2
= aTextPaMs
[2].GetPara();
2139 nLast2
= aTextPaMs
[3].GetPara() + ( aTextPaMs
[2] != aTextPaMs
[3] ? 1 : 0 );
2141 // adjust overlapping ranges
2142 if ( nLast1
> nFirst2
)
2146 // notify selection changes
2147 notifySelectionChange( nFirst1
, nLast1
);
2148 notifySelectionChange( nFirst2
, nLast2
);
2150 m_nSelectionFirstPara
= nNewFirstPara
;
2151 m_nSelectionFirstPos
= nNewFirstPos
;
2152 m_nSelectionLastPara
= nNewLastPara
;
2153 m_nSelectionLastPos
= nNewLastPos
;
2156 void Document::notifySelectionChange( sal_Int32 nFirst
, sal_Int32 nLast
)
2158 if ( nFirst
< nLast
)
2160 Paragraphs::iterator
aEnd( ::std::min( m_xParagraphs
->begin() + nLast
, m_aVisibleEnd
) );
2161 for ( Paragraphs::iterator aIt
= ::std::max( m_xParagraphs
->begin() + nFirst
, m_aVisibleBegin
); aIt
< aEnd
; ++aIt
)
2163 ::rtl::Reference
< ParagraphImpl
> xParagraph( getParagraph( aIt
) );
2164 if ( xParagraph
.is() )
2166 xParagraph
->notifyEvent(
2167 ::css::accessibility::AccessibleEventId::SELECTION_CHANGED
,
2168 ::css::uno::Any(), ::css::uno::Any() );
2169 xParagraph
->notifyEvent(
2170 ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
,
2171 ::css::uno::Any(), ::css::uno::Any() );
2177 void Document::justifySelection( TextPaM
& rTextStart
, TextPaM
& rTextEnd
)
2179 if ( rTextStart
> rTextEnd
)
2181 TextPaM
aTextPaM( rTextStart
);
2182 rTextStart
= rTextEnd
;
2183 rTextEnd
= aTextPaM
;
2187 void Document::disposeParagraphs()
2189 for (Paragraphs::iterator
aIt(m_xParagraphs
->begin());
2190 aIt
!= m_xParagraphs
->end(); ++aIt
)
2192 ::css::uno::Reference
< ::css::lang::XComponent
> xComponent(
2193 aIt
->getParagraph().get(), ::css::uno::UNO_QUERY
);
2194 if (xComponent
.is())
2195 xComponent
->dispose();
2200 ::css::uno::Any
Document::mapFontColor(::Color
const & rColor
)
2202 return ::css::uno::makeAny(
2203 static_cast< ::sal_Int32
>(COLORDATA_RGB(rColor
.GetColor())));
2204 // FIXME keep transparency?
2208 ::Color
Document::mapFontColor(::css::uno::Any
const & rColor
)
2210 ::sal_Int32 nColor
= 0;
2212 return ::Color(static_cast< ::ColorData
>(nColor
));
2216 ::css::uno::Any
Document::mapFontWeight(::FontWeight nWeight
)
2218 // Map from ::FontWeight to ::css:awt::FontWeight, depends on order of
2219 // elements in ::FontWeight (vcl/vclenum.hxx):
2220 static float const aWeight
[]
2221 = { ::css::awt::FontWeight::DONTKNOW
, // WEIGHT_DONTKNOW
2222 ::css::awt::FontWeight::THIN
, // WEIGHT_THIN
2223 ::css::awt::FontWeight::ULTRALIGHT
, // WEIGHT_ULTRALIGHT
2224 ::css::awt::FontWeight::LIGHT
, // WEIGHT_LIGHT
2225 ::css::awt::FontWeight::SEMILIGHT
, // WEIGHT_SEMILIGHT
2226 ::css::awt::FontWeight::NORMAL
, // WEIGHT_NORMAL
2227 ::css::awt::FontWeight::NORMAL
, // WEIGHT_MEDIUM
2228 ::css::awt::FontWeight::SEMIBOLD
, // WEIGHT_SEMIBOLD
2229 ::css::awt::FontWeight::BOLD
, // WEIGHT_BOLD
2230 ::css::awt::FontWeight::ULTRABOLD
, // WEIGHT_ULTRABOLD
2231 ::css::awt::FontWeight::BLACK
}; // WEIGHT_BLACK
2232 return ::css::uno::makeAny(aWeight
[nWeight
]);
2236 ::FontWeight
Document::mapFontWeight(::css::uno::Any
const & rWeight
)
2238 float nWeight
= ::css::awt::FontWeight::NORMAL
;
2239 rWeight
>>= nWeight
;
2240 return nWeight
<= ::css::awt::FontWeight::DONTKNOW
? WEIGHT_DONTKNOW
2241 : nWeight
<= ::css::awt::FontWeight::THIN
? WEIGHT_THIN
2242 : nWeight
<= ::css::awt::FontWeight::ULTRALIGHT
? WEIGHT_ULTRALIGHT
2243 : nWeight
<= ::css::awt::FontWeight::LIGHT
? WEIGHT_LIGHT
2244 : nWeight
<= ::css::awt::FontWeight::SEMILIGHT
? WEIGHT_SEMILIGHT
2245 : nWeight
<= ::css::awt::FontWeight::NORMAL
? WEIGHT_NORMAL
2246 : nWeight
<= ::css::awt::FontWeight::SEMIBOLD
? WEIGHT_SEMIBOLD
2247 : nWeight
<= ::css::awt::FontWeight::BOLD
? WEIGHT_BOLD
2248 : nWeight
<= ::css::awt::FontWeight::ULTRABOLD
? WEIGHT_ULTRABOLD