1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
20 #include <accessibility/extended/textwindowaccessibility.hxx>
21 #include "comphelper/accessibleeventnotifier.hxx"
22 #include "unotools/accessiblerelationsethelper.hxx"
23 #include <unotools/accessiblestatesethelper.hxx>
24 #include <vcl/window.hxx>
25 #include <toolkit/helper/convert.hxx>
29 #include <boost/unordered_map.hpp>
31 namespace accessibility
34 // Both ::osl::Mutex and ParagraphBase implement acquire and release, and thus
35 // ::rtl::Reference< Paragraph > does not work. So ParagraphImpl was factored
36 // out and ::rtl::Reference< ParagraphImpl > is used instead.
37 class Paragraph
: private ::osl::Mutex
, public ParagraphImpl
40 inline Paragraph(::rtl::Reference
< Document
> const & rDocument
,
41 Paragraphs::size_type nNumber
):
42 ParagraphImpl(rDocument
, nNumber
, *this) {}
45 void SfxListenerGuard::startListening(::SfxBroadcaster
& rNotifier
)
47 OSL_ENSURE(m_pNotifier
== 0, "called more than once");
48 m_pNotifier
= &rNotifier
;
49 m_rListener
.StartListening(*m_pNotifier
, true);
52 void SfxListenerGuard::endListening()
56 m_rListener
.EndListening(*m_pNotifier
);
61 void WindowListenerGuard::startListening(::Window
& rNotifier
)
63 OSL_ENSURE(m_pNotifier
== 0, "called more than once");
64 m_pNotifier
= &rNotifier
;
65 m_pNotifier
->AddEventListener(m_aListener
);
68 void WindowListenerGuard::endListening()
72 m_pNotifier
->RemoveEventListener(m_aListener
);
77 ParagraphImpl::ParagraphImpl(::rtl::Reference
< Document
> const & rDocument
,
78 Paragraphs::size_type nNumber
,
79 ::osl::Mutex
& rMutex
):
80 ParagraphBase(rMutex
),
81 m_xDocument(rDocument
),
85 m_aParagraphText
= m_xDocument
->retrieveParagraphText(this);
89 ParagraphImpl::numberChanged(bool bIncremented
)
97 void ParagraphImpl::textChanged()
99 OUString aParagraphText
= implGetText();
100 ::css::uno::Any aOldValue
, aNewValue
;
101 if ( implInitTextChangedEvent( m_aParagraphText
, aParagraphText
, aOldValue
, aNewValue
) )
103 m_aParagraphText
= aParagraphText
;
104 notifyEvent(::css::accessibility::AccessibleEventId::
106 aOldValue
, aNewValue
);
110 void ParagraphImpl::notifyEvent(::sal_Int16 nEventId
,
111 ::css::uno::Any
const & rOldValue
,
112 ::css::uno::Any
const & rNewValue
)
115 comphelper::AccessibleEventNotifier::addEvent( m_nClientId
, ::css::accessibility::AccessibleEventObject(
116 static_cast< ::cppu::OWeakObject
* >(this),
117 nEventId
, rNewValue
, rOldValue
) );
121 ::css::uno::Reference
< ::css::accessibility::XAccessibleContext
> SAL_CALL
122 ParagraphImpl::getAccessibleContext() throw (::css::uno::RuntimeException
)
129 ::sal_Int32 SAL_CALL
ParagraphImpl::getAccessibleChildCount()
130 throw (::css::uno::RuntimeException
)
137 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
138 ParagraphImpl::getAccessibleChild(::sal_Int32
)
139 throw (::css::lang::IndexOutOfBoundsException
,
140 ::css::uno::RuntimeException
)
143 throw ::css::lang::IndexOutOfBoundsException(
144 "textwindowaccessibility.cxx:"
145 " ParagraphImpl::getAccessibleChild",
146 static_cast< ::css::uno::XWeak
* >(this));
150 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
151 ParagraphImpl::getAccessibleParent()
152 throw (::css::uno::RuntimeException
)
155 return m_xDocument
->getAccessible();
159 ::sal_Int32 SAL_CALL
ParagraphImpl::getAccessibleIndexInParent()
160 throw (::css::uno::RuntimeException
)
163 return m_xDocument
->retrieveParagraphIndex(this);
167 ::sal_Int16 SAL_CALL
ParagraphImpl::getAccessibleRole()
168 throw (::css::uno::RuntimeException
)
171 return ::css::accessibility::AccessibleRole::PARAGRAPH
;
175 OUString SAL_CALL
ParagraphImpl::getAccessibleDescription()
176 throw (::css::uno::RuntimeException
)
183 OUString SAL_CALL
ParagraphImpl::getAccessibleName()
184 throw (::css::uno::RuntimeException
)
191 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
>
192 SAL_CALL
ParagraphImpl::getAccessibleRelationSet()
193 throw (::css::uno::RuntimeException
)
196 return m_xDocument
->retrieveParagraphRelationSet( this );
200 ::css::uno::Reference
< ::css::accessibility::XAccessibleStateSet
>
201 SAL_CALL
ParagraphImpl::getAccessibleStateSet()
202 throw (::css::uno::RuntimeException
)
206 // FIXME Notification of changes (STATE_CHANGED) missing when
207 // m_rView.IsReadOnly() changes:
208 return new ::utl::AccessibleStateSetHelper(
209 m_xDocument
->retrieveParagraphState(this));
213 ::css::lang::Locale SAL_CALL
ParagraphImpl::getLocale()
214 throw (::css::accessibility::IllegalAccessibleComponentStateException
,
215 ::css::uno::RuntimeException
)
218 return m_xDocument
->retrieveLocale();
222 ::sal_Bool SAL_CALL
ParagraphImpl::containsPoint(::css::awt::Point
const & rPoint
)
223 throw (::css::uno::RuntimeException
)
226 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
228 return rPoint
.X
>= 0 && rPoint
.X
< aRect
.Width
229 && rPoint
.Y
>= 0 && rPoint
.Y
< aRect
.Height
;
233 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
234 ParagraphImpl::getAccessibleAtPoint(::css::awt::Point
const &)
235 throw (::css::uno::RuntimeException
)
242 ::css::awt::Rectangle SAL_CALL
ParagraphImpl::getBounds()
243 throw (::css::uno::RuntimeException
)
246 return m_xDocument
->retrieveParagraphBounds(this, false);
250 ::css::awt::Point SAL_CALL
ParagraphImpl::getLocation()
251 throw (::css::uno::RuntimeException
)
254 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
256 return ::css::awt::Point(aRect
.X
, aRect
.Y
);
260 ::css::awt::Point SAL_CALL
ParagraphImpl::getLocationOnScreen()
261 throw (::css::uno::RuntimeException
)
264 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
266 return ::css::awt::Point(aRect
.X
, aRect
.Y
);
270 ::css::awt::Size SAL_CALL
ParagraphImpl::getSize()
271 throw (::css::uno::RuntimeException
)
274 ::css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
276 return ::css::awt::Size(aRect
.Width
, aRect
.Height
);
280 void SAL_CALL
ParagraphImpl::grabFocus() throw (::css::uno::RuntimeException
)
283 Window
* pWindow
= m_xDocument
->GetWindow();
286 pWindow
->GrabFocus();
290 m_xDocument
->changeParagraphSelection(this, 0, 0);
292 catch (const ::css::lang::IndexOutOfBoundsException
& rEx
)
295 "textwindowaccessibility.cxx: ParagraphImpl::grabFocus:"
296 " caught unexpected %s\n",
297 OUStringToOString(rEx
.Message
, RTL_TEXTENCODING_UTF8
).
303 ::css::uno::Any SAL_CALL
ParagraphImpl::getAccessibleKeyBinding()
304 throw (::css::uno::RuntimeException
)
307 return ::css::uno::Any();
311 ::css::util::Color SAL_CALL
ParagraphImpl::getForeground()
312 throw (::css::uno::RuntimeException
)
318 ::css::util::Color SAL_CALL
ParagraphImpl::getBackground()
319 throw (::css::uno::RuntimeException
)
325 ::sal_Int32 SAL_CALL
ParagraphImpl::getCaretPosition()
326 throw (::css::uno::RuntimeException
)
329 return m_xDocument
->retrieveParagraphCaretPosition(this);
333 ::sal_Bool SAL_CALL
ParagraphImpl::setCaretPosition(::sal_Int32 nIndex
)
334 throw (::css::lang::IndexOutOfBoundsException
,
335 ::css::uno::RuntimeException
)
338 m_xDocument
->changeParagraphSelection(this, nIndex
, nIndex
);
343 ::sal_Unicode SAL_CALL
ParagraphImpl::getCharacter(::sal_Int32 nIndex
)
344 throw (::css::lang::IndexOutOfBoundsException
,
345 ::css::uno::RuntimeException
)
348 return OCommonAccessibleText::getCharacter(nIndex
);
352 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
353 ParagraphImpl::getCharacterAttributes(::sal_Int32 nIndex
, const ::com::sun::star::uno::Sequence
< OUString
>& aRequestedAttributes
)
354 throw (::css::lang::IndexOutOfBoundsException
,
355 ::css::uno::RuntimeException
)
358 return m_xDocument
->retrieveCharacterAttributes( this, nIndex
, aRequestedAttributes
);
362 ::css::awt::Rectangle SAL_CALL
363 ParagraphImpl::getCharacterBounds(::sal_Int32 nIndex
)
364 throw (::css::lang::IndexOutOfBoundsException
,
365 ::css::uno::RuntimeException
)
368 ::css::awt::Rectangle
aBounds(m_xDocument
->retrieveCharacterBounds(this, nIndex
));
369 ::css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
370 aBounds
.X
-= aParaBounds
.X
;
371 aBounds
.Y
-= aParaBounds
.Y
;
376 ::sal_Int32 SAL_CALL
ParagraphImpl::getCharacterCount()
377 throw (::css::uno::RuntimeException
)
380 return OCommonAccessibleText::getCharacterCount();
385 ParagraphImpl::getIndexAtPoint(::css::awt::Point
const & rPoint
)
386 throw (::css::uno::RuntimeException
)
389 ::css::awt::Point
aPoint(rPoint
);
390 ::css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
391 aPoint
.X
+= aParaBounds
.X
;
392 aPoint
.Y
+= aParaBounds
.Y
;
393 return m_xDocument
->retrieveCharacterIndex(this, aPoint
);
397 OUString SAL_CALL
ParagraphImpl::getSelectedText()
398 throw (::css::uno::RuntimeException
)
402 return OCommonAccessibleText::getSelectedText();
406 ::sal_Int32 SAL_CALL
ParagraphImpl::getSelectionStart()
407 throw (::css::uno::RuntimeException
)
410 return OCommonAccessibleText::getSelectionStart();
414 ::sal_Int32 SAL_CALL
ParagraphImpl::getSelectionEnd()
415 throw (::css::uno::RuntimeException
)
418 return OCommonAccessibleText::getSelectionEnd();
422 ::sal_Bool SAL_CALL
ParagraphImpl::setSelection(::sal_Int32 nStartIndex
,
423 ::sal_Int32 nEndIndex
)
424 throw (::css::lang::IndexOutOfBoundsException
,
425 ::css::uno::RuntimeException
)
428 m_xDocument
->changeParagraphSelection(this, nStartIndex
, nEndIndex
);
433 OUString SAL_CALL
ParagraphImpl::getText()
434 throw (::css::uno::RuntimeException
)
437 return OCommonAccessibleText::getText();
441 OUString SAL_CALL
ParagraphImpl::getTextRange(::sal_Int32 nStartIndex
,
442 ::sal_Int32 nEndIndex
)
443 throw (::css::lang::IndexOutOfBoundsException
,
444 ::css::uno::RuntimeException
)
447 return OCommonAccessibleText::getTextRange(nStartIndex
, nEndIndex
);
451 ::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
)
454 return OCommonAccessibleText::getTextAtIndex(nIndex
, aTextType
);
458 ::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
)
461 return OCommonAccessibleText::getTextBeforeIndex(nIndex
, aTextType
);
465 ::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
)
468 return OCommonAccessibleText::getTextBehindIndex(nIndex
, aTextType
);
472 ::sal_Bool SAL_CALL
ParagraphImpl::copyText(::sal_Int32 nStartIndex
,
473 ::sal_Int32 nEndIndex
)
474 throw (::css::lang::IndexOutOfBoundsException
,
475 ::css::uno::RuntimeException
)
478 m_xDocument
->copyParagraphText(this, nStartIndex
, nEndIndex
);
483 ::sal_Bool SAL_CALL
ParagraphImpl::cutText(::sal_Int32 nStartIndex
,
484 ::sal_Int32 nEndIndex
)
485 throw (::css::lang::IndexOutOfBoundsException
,
486 ::css::uno::RuntimeException
)
489 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, true, false,
495 ::sal_Bool SAL_CALL
ParagraphImpl::pasteText(::sal_Int32 nIndex
)
496 throw (::css::lang::IndexOutOfBoundsException
,
497 ::css::uno::RuntimeException
)
500 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, true,
506 ::sal_Bool SAL_CALL
ParagraphImpl::deleteText(::sal_Int32 nStartIndex
,
507 ::sal_Int32 nEndIndex
)
508 throw (::css::lang::IndexOutOfBoundsException
,
509 ::css::uno::RuntimeException
)
512 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
518 ::sal_Bool SAL_CALL
ParagraphImpl::insertText(OUString
const & rText
,
520 throw (::css::lang::IndexOutOfBoundsException
,
521 ::css::uno::RuntimeException
)
524 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, false, rText
);
530 ParagraphImpl::replaceText(::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
531 OUString
const & rReplacement
)
532 throw (::css::lang::IndexOutOfBoundsException
,
533 ::css::uno::RuntimeException
)
536 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
542 ::sal_Bool SAL_CALL
ParagraphImpl::setAttributes(
543 ::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
544 ::css::uno::Sequence
< ::css::beans::PropertyValue
> const & rAttributeSet
)
545 throw (::css::lang::IndexOutOfBoundsException
,
546 ::css::uno::RuntimeException
)
549 m_xDocument
->changeParagraphAttributes(this, nStartIndex
, nEndIndex
,
555 ::sal_Bool SAL_CALL
ParagraphImpl::setText(OUString
const & rText
)
556 throw (::css::uno::RuntimeException
)
559 m_xDocument
->changeParagraphText(this, rText
);
564 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
565 ParagraphImpl::getDefaultAttributes(const ::css::uno::Sequence
< OUString
>& RequestedAttributes
)
566 throw (::css::uno::RuntimeException
)
569 return m_xDocument
->retrieveDefaultAttributes( this, RequestedAttributes
);
573 ::css::uno::Sequence
< ::css::beans::PropertyValue
> SAL_CALL
574 ParagraphImpl::getRunAttributes(::sal_Int32 Index
, const ::css::uno::Sequence
< OUString
>& RequestedAttributes
)
575 throw (::css::lang::IndexOutOfBoundsException
,
576 ::css::uno::RuntimeException
)
579 return m_xDocument
->retrieveRunAttributes( this, Index
, RequestedAttributes
);
583 ::sal_Int32 SAL_CALL
ParagraphImpl::getLineNumberAtIndex( ::sal_Int32 nIndex
)
584 throw (::css::lang::IndexOutOfBoundsException
,
585 ::css::uno::RuntimeException
)
589 ::sal_Int32 nLineNo
= -1;
590 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
, &nLineNo
);
596 ::css::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextAtLineNumber( ::sal_Int32 nLineNo
)
597 throw (::css::lang::IndexOutOfBoundsException
,
598 ::css::uno::RuntimeException
)
602 ::css::i18n::Boundary aBoundary
=
603 m_xDocument
->retrieveParagraphBoundaryOfLine( this, nLineNo
);
605 return ::css::accessibility::TextSegment( getTextRange(aBoundary
.startPos
, aBoundary
.endPos
),
606 aBoundary
.startPos
, aBoundary
.endPos
);
610 ::css::accessibility::TextSegment SAL_CALL
ParagraphImpl::getTextAtLineWithCaret( )
611 throw (::css::uno::RuntimeException
)
615 sal_Int32 nLineNo
= getNumberOfLineWithCaret();
618 return ( nLineNo
>= 0 ) ?
619 getTextAtLineNumber( nLineNo
) :
620 ::css::accessibility::TextSegment();
621 } catch (const ::css::lang::IndexOutOfBoundsException
&) {
622 throw ::css::uno::RuntimeException(
623 "textwindowaccessibility.cxx:"
624 " ParagraphImpl::getTextAtLineWithCaret",
625 static_cast< ::css::uno::XWeak
* >( this ) );
630 ::sal_Int32 SAL_CALL
ParagraphImpl::getNumberOfLineWithCaret( )
631 throw (::css::uno::RuntimeException
)
634 return m_xDocument
->retrieveParagraphLineWithCursor(this);
639 void SAL_CALL
ParagraphImpl::addAccessibleEventListener(
640 ::css::uno::Reference
<
641 ::css::accessibility::XAccessibleEventListener
> const & rListener
)
642 throw (::css::uno::RuntimeException
)
646 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
647 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
650 rListener
->disposing(::css::lang::EventObject(
651 static_cast< ::cppu::OWeakObject
* >(this)));
656 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
657 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, rListener
);
663 void SAL_CALL
ParagraphImpl::removeAccessibleEventListener(
664 ::css::uno::Reference
<
665 ::css::accessibility::XAccessibleEventListener
> const & rListener
)
666 throw (::css::uno::RuntimeException
)
668 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
670 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
671 if (rListener
.is() && m_nClientId
!= 0
672 && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, rListener
) == 0)
680 // no listeners anymore
681 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
682 // and at least to us not firing any events anymore, in case somebody calls
683 // NotifyAccessibleEvent, again
684 comphelper::AccessibleEventNotifier::revokeClient(nId
);
689 void SAL_CALL
ParagraphImpl::disposing()
691 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
693 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
698 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId
, *this);
702 OUString
ParagraphImpl::implGetText()
704 return m_xDocument
->retrieveParagraphText(this);
708 ::css::lang::Locale
ParagraphImpl::implGetLocale()
710 return m_xDocument
->retrieveLocale();
714 void ParagraphImpl::implGetSelection(::sal_Int32
& rStartIndex
,
715 ::sal_Int32
& rEndIndex
)
717 m_xDocument
->retrieveParagraphSelection(this, &rStartIndex
, &rEndIndex
);
721 void ParagraphImpl::implGetParagraphBoundary( ::css::i18n::Boundary
& rBoundary
,
724 OUString
sText( implGetText() );
725 ::sal_Int32 nLength
= sText
.getLength();
727 if ( implIsValidIndex( nIndex
, nLength
) )
729 rBoundary
.startPos
= 0;
730 rBoundary
.endPos
= nLength
;
734 rBoundary
.startPos
= nIndex
;
735 rBoundary
.endPos
= nIndex
;
740 void ParagraphImpl::implGetLineBoundary( ::css::i18n::Boundary
& rBoundary
,
743 OUString
sText( implGetText() );
744 ::sal_Int32 nLength
= sText
.getLength();
746 if ( implIsValidIndex( nIndex
, nLength
) || nIndex
== nLength
)
748 ::css::i18n::Boundary aBoundary
=
749 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
);
750 rBoundary
.startPos
= aBoundary
.startPos
;
751 rBoundary
.endPos
= aBoundary
.endPos
;
755 rBoundary
.startPos
= nIndex
;
756 rBoundary
.endPos
= nIndex
;
761 void ParagraphImpl::checkDisposed()
763 ::osl::MutexGuard
aGuard(rBHelper
.rMutex
);
764 if (!(rBHelper
.bDisposed
|| rBHelper
.bInDispose
))
766 throw ::css::lang::DisposedException(
767 OUString(), static_cast< ::css::uno::XWeak
* >(this));
770 Document::Document(::VCLXWindow
* pVclXWindow
, ::TextEngine
& rEngine
,
771 ::TextView
& rView
, bool bCompoundControlChild
):
772 VCLXAccessibleComponent(pVclXWindow
),
773 m_xAccessible(pVclXWindow
),
776 m_aEngineListener(*this),
777 m_aViewListener(LINK(this, Document
, WindowEventHandler
)),
778 m_bCompoundControlChild(bCompoundControlChild
)
781 ::css::lang::Locale
Document::retrieveLocale()
783 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
784 return m_rEngine
.GetLocale();
787 ::sal_Int32
Document::retrieveParagraphIndex(ParagraphImpl
const * pParagraph
)
789 ::osl::MutexGuard
aInternalGuard(GetMutex());
791 // If a client holds on to a Paragraph that is no longer visible, it can
792 // happen that this Paragraph lies outside the range from m_aVisibleBegin
793 // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
794 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
795 + pParagraph
->getNumber());
796 return aPara
< m_aVisibleBegin
|| aPara
>= m_aVisibleEnd
797 ? -1 : static_cast< ::sal_Int32
>(aPara
- m_aVisibleBegin
);
798 // XXX numeric overflow
801 ::sal_Int64
Document::retrieveParagraphState(ParagraphImpl
const * pParagraph
)
803 ::osl::MutexGuard
aInternalGuard(GetMutex());
805 // If a client holds on to a Paragraph that is no longer visible, it can
806 // happen that this Paragraph lies outside the range from m_aVisibleBegin
807 // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
809 = (static_cast< ::sal_Int64
>(1)
810 << ::css::accessibility::AccessibleStateType::ENABLED
)
811 | (static_cast< ::sal_Int64
>(1)
812 << ::css::accessibility::AccessibleStateType::SENSITIVE
)
813 | (static_cast< ::sal_Int64
>(1)
814 << ::css::accessibility::AccessibleStateType::FOCUSABLE
)
815 | (static_cast< ::sal_Int64
>(1)
816 << ::css::accessibility::AccessibleStateType::MULTI_LINE
);
817 if (!m_rView
.IsReadOnly())
818 nState
|= (static_cast< ::sal_Int64
>(1)
819 << ::css::accessibility::AccessibleStateType::EDITABLE
);
820 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
821 + pParagraph
->getNumber());
822 if (aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
825 |= (static_cast< ::sal_Int64
>(1)
826 << ::css::accessibility::AccessibleStateType::VISIBLE
)
827 | (static_cast< ::sal_Int64
>(1)
828 << ::css::accessibility::AccessibleStateType::SHOWING
);
829 if (aPara
== m_aFocused
)
830 nState
|= (static_cast< ::sal_Int64
>(1)
831 << ::css::accessibility::AccessibleStateType::FOCUSED
);
836 ::css::awt::Rectangle
837 Document::retrieveParagraphBounds(ParagraphImpl
const * pParagraph
,
840 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
841 ::osl::MutexGuard
aInternalGuard(GetMutex());
843 // If a client holds on to a Paragraph that is no longer visible (as it
844 // scrolled out the top of the view), it can happen that this Paragraph
845 // lies before m_aVisibleBegin. In that case, calculate the vertical
846 // position of the Paragraph starting at paragraph 0, otherwise optimize
847 // and start at m_aVisibleBegin:
848 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
849 + pParagraph
->getNumber());
851 Paragraphs::iterator aIt
;
852 if (aPara
< m_aVisibleBegin
)
855 aIt
= m_xParagraphs
->begin();
859 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
860 aIt
= m_aVisibleBegin
;
862 for (; aIt
!= aPara
; ++aIt
)
863 nPos
+= aIt
->getHeight();
867 aOrig
= m_rView
.GetWindow()->OutputToAbsoluteScreenPixel(aOrig
);
869 return ::css::awt::Rectangle(
870 static_cast< ::sal_Int32
>(aOrig
.X()),
871 static_cast< ::sal_Int32
>(aOrig
.Y()) + nPos
- m_nViewOffset
,
872 m_rView
.GetWindow()->GetOutputSizePixel().Width(), aPara
->getHeight());
873 // XXX numeric overflow (3x)
877 Document::retrieveParagraphText(ParagraphImpl
const * pParagraph
)
879 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
880 ::osl::MutexGuard
aInternalGuard(GetMutex());
881 return m_rEngine
.GetText(static_cast< ::sal_uLong
>(pParagraph
->getNumber()));
882 // numeric overflow cannot happen here
885 void Document::retrieveParagraphSelection(ParagraphImpl
const * pParagraph
,
886 ::sal_Int32
* pBegin
,
889 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
890 ::osl::MutexGuard
aInternalGuard(GetMutex());
891 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
892 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
893 TextPaM
aStartPaM( rSelection
.GetStart() );
894 TextPaM
aEndPaM( rSelection
.GetEnd() );
895 TextPaM
aMinPaM( ::std::min( aStartPaM
, aEndPaM
) );
896 TextPaM
aMaxPaM( ::std::max( aStartPaM
, aEndPaM
) );
898 if ( nNumber
>= aMinPaM
.GetPara() && nNumber
<= aMaxPaM
.GetPara() )
900 *pBegin
= nNumber
> aMinPaM
.GetPara()
902 : static_cast< ::sal_Int32
>( aMinPaM
.GetIndex() );
903 // XXX numeric overflow
904 *pEnd
= nNumber
< aMaxPaM
.GetPara()
905 ? static_cast< ::sal_Int32
>( m_rEngine
.GetText(static_cast< ::sal_uLong
>(nNumber
)).Len() )
906 : static_cast< ::sal_Int32
>( aMaxPaM
.GetIndex() );
907 // XXX numeric overflow (3x)
909 if ( aStartPaM
> aEndPaM
)
910 ::std::swap( *pBegin
, *pEnd
);
919 ::sal_Int32
Document::retrieveParagraphCaretPosition(ParagraphImpl
const * pParagraph
)
921 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
922 ::osl::MutexGuard
aInternalGuard(GetMutex());
923 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
924 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
925 TextPaM
aEndPaM( rSelection
.GetEnd() );
927 return aEndPaM
.GetPara() == nNumber
928 ? static_cast< ::sal_Int32
>(aEndPaM
.GetIndex()) : -1;
931 ::css::awt::Rectangle
932 Document::retrieveCharacterBounds(ParagraphImpl
const * pParagraph
,
935 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
936 ::osl::MutexGuard
aInternalGuard(GetMutex());
937 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
938 sal_Int32 nLength
= m_rEngine
.GetText(nNumber
).Len();
939 // XXX numeric overflow
940 if (nIndex
< 0 || nIndex
> nLength
)
941 throw ::css::lang::IndexOutOfBoundsException(
942 "textwindowaccessibility.cxx:"
943 " Document::retrieveCharacterAttributes",
944 static_cast< ::css::uno::XWeak
* >(this));
945 ::css::awt::Rectangle
aBounds( 0, 0, 0, 0 );
946 if ( nIndex
== nLength
)
948 aBounds
= AWTRectangle(
949 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
950 static_cast< ::sal_uInt16
>(nIndex
))));
955 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
956 static_cast< ::sal_uInt16
>(nIndex
))));
957 // XXX numeric overflow
959 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
960 static_cast< ::sal_uInt16
>(nIndex
)
962 // XXX numeric overflow (2x)
963 // FIXME If the vertical extends of the two cursors do not match, assume
964 // nIndex is the last character on the line; the bounding box will then
965 // extend to m_rEnginge.GetMaxTextWidth():
966 ::sal_Int32 nWidth
= (aLeft
.Top() == aRight
.Top()
967 && aLeft
.Bottom() == aRight
.Bottom())
968 ? static_cast< ::sal_Int32
>(aRight
.Left() - aLeft
.Left())
969 : static_cast< ::sal_Int32
>(m_rEngine
.GetMaxTextWidth()
971 // XXX numeric overflow (4x)
972 aBounds
= ::css::awt::Rectangle(static_cast< ::sal_Int32
>(aLeft
.Left()),
973 static_cast< ::sal_Int32
>(aLeft
.Top() - m_nViewOffset
),
975 static_cast< ::sal_Int32
>(aLeft
.Bottom()
977 // XXX numeric overflow (4x)
982 ::sal_Int32
Document::retrieveCharacterIndex(ParagraphImpl
const * pParagraph
,
983 ::css::awt::Point
const & rPoint
)
985 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
986 ::osl::MutexGuard
aInternalGuard(GetMutex());
987 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
988 // XXX numeric overflow
989 ::TextPaM
aPaM(m_rEngine
.GetPaM(::Point(static_cast< long >(rPoint
.X
),
990 static_cast< long >(rPoint
.Y
))));
991 // XXX numeric overflow (2x)
992 return aPaM
.GetPara() == nNumber
993 ? static_cast< ::sal_Int32
>(aPaM
.GetIndex()) : -1;
994 // XXX numeric overflow
997 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
998 Document::retrieveCharacterAttributes(
999 ParagraphImpl
const * pParagraph
, ::sal_Int32 nIndex
,
1000 const ::css::uno::Sequence
< OUString
>& aRequestedAttributes
)
1002 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1003 ::osl::MutexGuard
aInternalGuard(GetMutex());
1004 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1005 // XXX numeric overflow
1006 if (nIndex
< 0 || nIndex
>= m_rEngine
.GetText(nNumber
).Len())
1007 throw ::css::lang::IndexOutOfBoundsException(
1008 "textwindowaccessibility.cxx:"
1009 " Document::retrieveCharacterAttributes",
1010 static_cast< ::css::uno::XWeak
* >(this));
1012 // retrieve default attributes
1013 tPropValMap aCharAttrSeq
;
1014 retrieveDefaultAttributesImpl( pParagraph
, aRequestedAttributes
, aCharAttrSeq
);
1016 // retrieve run attributes
1017 tPropValMap aRunAttrSeq
;
1018 retrieveRunAttributesImpl( pParagraph
, nIndex
, aRequestedAttributes
, aRunAttrSeq
);
1020 // merge default and run attributes
1021 for ( tPropValMap::const_iterator aRunIter
= aRunAttrSeq
.begin();
1022 aRunIter
!= aRunAttrSeq
.end();
1025 aCharAttrSeq
[ aRunIter
->first
] = aRunIter
->second
;
1028 return convertHashMapToSequence( aCharAttrSeq
);
1031 void Document::retrieveDefaultAttributesImpl(
1032 ParagraphImpl
const * pParagraph
,
1033 const ::css::uno::Sequence
< OUString
>& RequestedAttributes
,
1034 tPropValMap
& rDefAttrSeq
)
1036 // default attributes are not supported by text engine
1038 (void) RequestedAttributes
;
1042 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1043 Document::retrieveDefaultAttributes(
1044 ParagraphImpl
const * pParagraph
,
1045 const ::css::uno::Sequence
< OUString
>& RequestedAttributes
)
1047 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1048 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1050 tPropValMap aDefAttrSeq
;
1051 retrieveDefaultAttributesImpl( pParagraph
, RequestedAttributes
, aDefAttrSeq
);
1052 return convertHashMapToSequence( aDefAttrSeq
);
1056 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1057 Document::convertHashMapToSequence(tPropValMap
& rAttrSeq
)
1059 ::css::uno::Sequence
< ::css::beans::PropertyValue
> aValues( rAttrSeq
.size() );
1060 ::css::beans::PropertyValue
* pValues
= aValues
.getArray();
1062 for ( tPropValMap::const_iterator aIter
= rAttrSeq
.begin();
1063 aIter
!= rAttrSeq
.end();
1066 pValues
[i
] = aIter
->second
;
1072 void Document::retrieveRunAttributesImpl(
1073 ParagraphImpl
const * pParagraph
, ::sal_Int32 Index
,
1074 const ::css::uno::Sequence
< OUString
>& RequestedAttributes
,
1075 tPropValMap
& rRunAttrSeq
)
1077 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1078 ::TextPaM
aPaM( nNumber
, static_cast< ::sal_uInt16
>( Index
) );
1079 // XXX numeric overflow
1080 // FIXME TEXTATTR_HYPERLINK ignored:
1081 ::TextAttribFontColor
const * pColor
1082 = static_cast< ::TextAttribFontColor
const * >(
1083 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTCOLOR
) );
1084 ::TextAttribFontWeight
const * pWeight
1085 = static_cast< ::TextAttribFontWeight
const * >(
1086 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTWEIGHT
) );
1087 tPropValMap aRunAttrSeq
;
1090 ::css::beans::PropertyValue aPropVal
;
1091 aPropVal
.Name
= "CharColor";
1092 aPropVal
.Handle
= -1;
1093 aPropVal
.Value
= mapFontColor( pColor
->GetColor() );
1094 aPropVal
.State
= ::css::beans::PropertyState_DIRECT_VALUE
;
1095 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1099 ::css::beans::PropertyValue aPropVal
;
1100 aPropVal
.Name
= "CharWeight";
1101 aPropVal
.Handle
= -1;
1102 aPropVal
.Value
= mapFontWeight( pWeight
->getFontWeight() );
1103 aPropVal
.State
= ::css::beans::PropertyState_DIRECT_VALUE
;
1104 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1106 if ( RequestedAttributes
.getLength() == 0 )
1108 rRunAttrSeq
= aRunAttrSeq
;
1112 const OUString
* pReqAttrs
= RequestedAttributes
.getConstArray();
1113 const ::sal_Int32 nLength
= RequestedAttributes
.getLength();
1114 for ( ::sal_Int32 i
= 0; i
< nLength
; ++i
)
1116 tPropValMap::iterator aIter
= aRunAttrSeq
.find( pReqAttrs
[i
] );
1117 if ( aIter
!= aRunAttrSeq
.end() )
1119 rRunAttrSeq
[ (*aIter
).first
] = (*aIter
).second
;
1125 ::css::uno::Sequence
< ::css::beans::PropertyValue
>
1126 Document::retrieveRunAttributes(
1127 ParagraphImpl
const * pParagraph
, ::sal_Int32 Index
,
1128 const ::css::uno::Sequence
< OUString
>& RequestedAttributes
)
1130 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1131 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1132 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1133 // XXX numeric overflow
1134 if ( Index
< 0 || Index
>= m_rEngine
.GetText(nNumber
).Len() )
1135 throw ::css::lang::IndexOutOfBoundsException(
1136 "textwindowaccessibility.cxx:"
1137 " Document::retrieveRunAttributes",
1138 static_cast< ::css::uno::XWeak
* >( this ) );
1140 tPropValMap aRunAttrSeq
;
1141 retrieveRunAttributesImpl( pParagraph
, Index
, RequestedAttributes
, aRunAttrSeq
);
1142 return convertHashMapToSequence( aRunAttrSeq
);
1145 void Document::changeParagraphText(ParagraphImpl
* pParagraph
,
1146 OUString
const & rText
)
1148 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1150 ::osl::MutexGuard
aInternalGuard(GetMutex());
1151 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1152 // XXX numeric overflow
1153 changeParagraphText(nNumber
, 0, m_rEngine
.GetTextLen(nNumber
), false,
1158 void Document::changeParagraphText(ParagraphImpl
* pParagraph
,
1159 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1160 bool bCut
, bool bPaste
,
1161 OUString
const & rText
)
1163 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1165 ::osl::MutexGuard
aInternalGuard(GetMutex());
1166 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1167 // XXX numeric overflow
1168 if (nBegin
< 0 || nBegin
> nEnd
1169 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1170 throw ::css::lang::IndexOutOfBoundsException(
1171 "textwindowaccessibility.cxx:"
1172 " Document::changeParagraphText",
1173 static_cast< ::css::uno::XWeak
* >(this));
1174 changeParagraphText(nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1175 static_cast< ::sal_uInt16
>(nEnd
), bCut
, bPaste
, rText
);
1176 // XXX numeric overflow (2x)
1180 void Document::copyParagraphText(ParagraphImpl
const * pParagraph
,
1181 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1183 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1185 ::osl::MutexGuard
aInternalGuard(GetMutex());
1186 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1187 // XXX numeric overflow
1188 if (nBegin
< 0 || nBegin
> nEnd
1189 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1190 throw ::css::lang::IndexOutOfBoundsException(
1191 "textwindowaccessibility.cxx:"
1192 " Document::copyParagraphText",
1193 static_cast< ::css::uno::XWeak
* >(this));
1194 m_rView
.SetSelection(
1195 ::TextSelection(::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nBegin
)),
1196 ::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nEnd
))));
1197 // XXX numeric overflow (2x)
1202 void Document::changeParagraphAttributes(
1203 ParagraphImpl
* pParagraph
, ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1204 ::css::uno::Sequence
< ::css::beans::PropertyValue
> const & rAttributeSet
)
1206 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1208 ::osl::MutexGuard
aInternalGuard(GetMutex());
1209 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1210 // XXX numeric overflow
1211 if (nBegin
< 0 || nBegin
> nEnd
1212 || nEnd
> m_rEngine
.GetText(nNumber
).Len())
1213 throw ::css::lang::IndexOutOfBoundsException(
1214 "textwindowaccessibility.cxx:"
1215 " Document::changeParagraphAttributes",
1216 static_cast< ::css::uno::XWeak
* >(this));
1218 // FIXME The new attributes are added to any attributes already set,
1219 // they do not replace the old attributes as required by
1220 // XAccessibleEditableText.setAttributes:
1221 for (::sal_Int32 i
= 0; i
< rAttributeSet
.getLength(); ++i
)
1222 if ( rAttributeSet
[i
].Name
== "CharColor" )
1223 m_rEngine
.SetAttrib(::TextAttribFontColor(
1224 mapFontColor(rAttributeSet
[i
].Value
)),
1225 nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1226 static_cast< ::sal_uInt16
>(nEnd
));
1227 // XXX numeric overflow (2x)
1228 else if ( rAttributeSet
[i
].Name
== "CharWeight" )
1229 m_rEngine
.SetAttrib(::TextAttribFontWeight(
1230 mapFontWeight(rAttributeSet
[i
].Value
)),
1231 nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1232 static_cast< ::sal_uInt16
>(nEnd
));
1233 // XXX numeric overflow (2x)
1237 void Document::changeParagraphSelection(ParagraphImpl
* pParagraph
,
1238 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1240 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1242 ::osl::MutexGuard
aInternalGuard(GetMutex());
1243 ::sal_uLong nNumber
= static_cast< ::sal_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(
1248 "textwindowaccessibility.cxx:"
1249 " Document::changeParagraphSelection",
1250 static_cast< ::css::uno::XWeak
* >(this));
1251 m_rView
.SetSelection(
1252 ::TextSelection(::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nBegin
)),
1253 ::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nEnd
))));
1254 // XXX numeric overflow (2x)
1258 ::css::i18n::Boundary
1259 Document::retrieveParagraphLineBoundary( ParagraphImpl
const * pParagraph
,
1260 ::sal_Int32 nIndex
, ::sal_Int32
*pLineNo
)
1262 ::css::i18n::Boundary aBoundary
;
1263 aBoundary
.startPos
= nIndex
;
1264 aBoundary
.endPos
= nIndex
;
1266 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1268 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1269 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1270 if ( nIndex
< 0 || nIndex
> m_rEngine
.GetText( nNumber
).Len() )
1271 throw ::css::lang::IndexOutOfBoundsException(
1272 "textwindowaccessibility.cxx:"
1273 " Document::retrieveParagraphLineBoundary",
1274 static_cast< ::css::uno::XWeak
* >( this ) );
1275 ::sal_Int32 nLineStart
= 0;
1276 ::sal_Int32 nLineEnd
= 0;
1277 ::sal_uInt16 nLineCount
= m_rEngine
.GetLineCount( nNumber
);
1278 for ( ::sal_uInt16 nLine
= 0; nLine
< nLineCount
; ++nLine
)
1280 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1281 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1282 nLineStart
= nLineEnd
;
1283 nLineEnd
+= nLineLength
;
1284 if ( nIndex
>= nLineStart
&& ( ( nLine
== nLineCount
- 1 ) ? nIndex
<= nLineEnd
: nIndex
< nLineEnd
) )
1286 aBoundary
.startPos
= nLineStart
;
1287 aBoundary
.endPos
= nLineEnd
;
1298 ::css::i18n::Boundary
1299 Document::retrieveParagraphBoundaryOfLine( ParagraphImpl
const * pParagraph
,
1300 ::sal_Int32 nLineNo
)
1302 ::css::i18n::Boundary aBoundary
;
1303 aBoundary
.startPos
= 0;
1304 aBoundary
.endPos
= 0;
1306 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1308 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1309 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1310 if ( nLineNo
>= m_rEngine
.GetLineCount( nNumber
) )
1311 throw ::css::lang::IndexOutOfBoundsException(
1312 "textwindowaccessibility.cxx:"
1313 " Document::retrieveParagraphBoundaryOfLine",
1314 static_cast< ::css::uno::XWeak
* >( this ) );
1315 ::sal_Int32 nLineStart
= 0;
1316 ::sal_Int32 nLineEnd
= 0;
1317 for ( ::sal_uInt16 nLine
= 0; nLine
<= nLineNo
; ++nLine
)
1319 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1320 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1321 nLineStart
= nLineEnd
;
1322 nLineEnd
+= nLineLength
;
1325 aBoundary
.startPos
= nLineStart
;
1326 aBoundary
.endPos
= nLineEnd
;
1332 sal_Int32
Document::retrieveParagraphLineWithCursor( ParagraphImpl
const * pParagraph
)
1334 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1335 ::osl::MutexGuard
aInternalGuard(GetMutex());
1336 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
1337 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
1338 TextPaM
aEndPaM( rSelection
.GetEnd() );
1340 return aEndPaM
.GetPara() == nNumber
1341 ? m_rView
.GetLineNumberOfCursorInSelection() : -1;
1345 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
>
1346 Document::retrieveParagraphRelationSet( ParagraphImpl
const * pParagraph
)
1348 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1350 ::utl::AccessibleRelationSetHelper
* pRelationSetHelper
= new ::utl::AccessibleRelationSetHelper();
1351 ::css::uno::Reference
< ::css::accessibility::XAccessibleRelationSet
> xSet
= pRelationSetHelper
;
1353 Paragraphs::iterator
aPara( m_xParagraphs
->begin() + pParagraph
->getNumber() );
1355 if ( aPara
> m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
1357 ::css::uno::Sequence
< ::css::uno::Reference
< ::css::uno::XInterface
> > aSequence(1);
1358 aSequence
[0] = getAccessibleChild( aPara
- 1 );
1359 ::css::accessibility::AccessibleRelation
aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM
, aSequence
);
1360 pRelationSetHelper
->AddRelation( aRelation
);
1363 if ( aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
-1 )
1365 ::css::uno::Sequence
< ::css::uno::Reference
< ::css::uno::XInterface
> > aSequence(1);
1366 aSequence
[0] = getAccessibleChild( aPara
+ 1 );
1367 ::css::accessibility::AccessibleRelation
aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO
, aSequence
);
1368 pRelationSetHelper
->AddRelation( aRelation
);
1374 void Document::ProcessWindowEvent( const VclWindowEvent
& rVclWindowEvent
)
1376 switch ( rVclWindowEvent
.GetId() )
1378 case VCLEVENT_WINDOW_GETFOCUS
:
1379 case VCLEVENT_WINDOW_LOSEFOCUS
:
1381 // #107179# if our parent is a compound control (e.g. MultiLineEdit),
1382 // suppress the window focus events here
1383 if ( !m_bCompoundControlChild
)
1384 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent
);
1388 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent
);
1393 ::sal_Int32 SAL_CALL
Document::getAccessibleChildCount()
1394 throw (::css::uno::RuntimeException
)
1396 ::comphelper::OExternalLockGuard
aGuard(this);
1398 return m_aVisibleEnd
- m_aVisibleBegin
;
1402 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
1403 Document::getAccessibleChild(::sal_Int32 i
)
1404 throw (::css::lang::IndexOutOfBoundsException
,
1405 ::css::uno::RuntimeException
)
1407 ::comphelper::OExternalLockGuard
aGuard(this);
1409 if (i
< 0 || i
>= m_aVisibleEnd
- m_aVisibleBegin
)
1410 throw ::css::lang::IndexOutOfBoundsException(
1411 "textwindowaccessibility.cxx:"
1412 " Document::getAccessibleChild",
1413 static_cast< ::css::uno::XWeak
* >(this));
1414 return getAccessibleChild(m_aVisibleBegin
1415 + static_cast< Paragraphs::size_type
>(i
));
1419 ::sal_Int16 SAL_CALL
Document::getAccessibleRole()
1420 throw (::css::uno::RuntimeException
)
1422 return ::css::accessibility::AccessibleRole::TEXT_FRAME
;
1426 ::css::uno::Reference
< ::css::accessibility::XAccessible
> SAL_CALL
1427 Document::getAccessibleAtPoint(::css::awt::Point
const & rPoint
)
1428 throw (::css::uno::RuntimeException
)
1430 ::comphelper::OExternalLockGuard
aGuard(this);
1433 && rPoint
.X
< m_rView
.GetWindow()->GetOutputSizePixel().Width()
1434 && rPoint
.Y
>= 0 && rPoint
.Y
< m_nViewHeight
)
1436 ::sal_Int32 nOffset
= m_nViewOffset
+ rPoint
.Y
; // XXX numeric overflow
1437 ::sal_Int32 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
1438 for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1441 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1443 return getAccessibleChild(aIt
);
1450 void SAL_CALL
Document::disposing()
1452 m_aEngineListener
.endListening();
1453 m_aViewListener
.endListening();
1454 if (m_xParagraphs
.get() != 0)
1455 disposeParagraphs();
1456 VCLXAccessibleComponent::disposing();
1460 void Document::Notify(::SfxBroadcaster
&, ::SfxHint
const & rHint
)
1462 if (rHint
.ISA(::TextHint
))
1464 ::TextHint
const & rTextHint
1465 = static_cast< ::TextHint
const & >(rHint
);
1466 switch (rTextHint
.GetId())
1468 case TEXT_HINT_PARAINSERTED
:
1469 case TEXT_HINT_PARAREMOVED
:
1470 // TEXT_HINT_PARAINSERTED and TEXT_HINT_PARAREMOVED are sent at
1471 // "unsafe" times (when the text engine has not yet re-formatted its
1472 // content), so that for example calling ::TextEngine::GetTextHeight
1473 // from within the code that handles TEXT_HINT_PARAINSERTED causes
1474 // trouble within the text engine. Therefore, these hints are just
1475 // buffered until a following ::TextEngine::FormatDoc causes a
1476 // TEXT_HINT_TEXTFORMATTED to come in:
1477 case TEXT_HINT_FORMATPARA
:
1478 // ::TextEngine::FormatDoc sends a sequence of
1479 // TEXT_HINT_FORMATPARAs, followed by an optional
1480 // TEXT_HINT_TEXTHEIGHTCHANGED, followed in all cases by one
1481 // TEXT_HINT_TEXTFORMATTED. Only the TEXT_HINT_FORMATPARAs contain
1482 // the the numbers of the affected paragraphs, but they are sent
1483 // before the changes are applied. Therefore, TEXT_HINT_FORMATPARAs
1484 // are just buffered until another hint comes in:
1486 ::osl::MutexGuard
aInternalGuard(GetMutex());
1490 m_aParagraphNotifications
.push(rTextHint
);
1493 case TEXT_HINT_TEXTFORMATTED
:
1494 case TEXT_HINT_TEXTHEIGHTCHANGED
:
1495 case TEXT_HINT_MODIFIED
:
1497 ::osl::MutexGuard
aInternalGuard(GetMutex());
1500 handleParagraphNotifications();
1503 case TEXT_HINT_VIEWSCROLLED
:
1505 ::osl::MutexGuard
aInternalGuard(GetMutex());
1508 handleParagraphNotifications();
1510 ::sal_Int32 nOffset
= static_cast< ::sal_Int32
>(
1511 m_rView
.GetStartDocPos().Y());
1512 // XXX numeric overflow
1513 if (nOffset
!= m_nViewOffset
)
1515 m_nViewOffset
= nOffset
;
1517 Paragraphs::iterator
aOldVisibleBegin(
1519 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1521 determineVisibleRange();
1523 notifyVisibleRangeChanges(aOldVisibleBegin
,
1525 m_xParagraphs
->end());
1529 case TEXT_HINT_VIEWSELECTIONCHANGED
:
1531 ::osl::MutexGuard
aInternalGuard(GetMutex());
1535 if (m_aParagraphNotifications
.empty())
1537 handleSelectionChangeNotification();
1541 // TEXT_HINT_VIEWSELECTIONCHANGED is sometimes sent at
1542 // "unsafe" times (when the text engine has not yet re-
1543 // formatted its content), so that for example calling
1544 // ::TextEngine::GetTextHeight from within the code that
1545 // handles a previous TEXT_HINT_PARAINSERTED causes
1546 // trouble within the text engine. Therefore, these
1547 // hints are just buffered (along with
1548 // TEXT_HINT_PARAINSERTED/REMOVED/FORMATPARA) until a
1549 // following ::TextEngine::FormatDoc causes a
1550 // TEXT_HINT_TEXTFORMATTED to come in:
1551 m_bSelectionChangedNotification
= true;
1559 IMPL_LINK(Document
, WindowEventHandler
, ::VclSimpleEvent
*, pEvent
)
1561 switch (pEvent
->GetId())
1563 case VCLEVENT_WINDOW_RESIZE
:
1565 ::osl::MutexGuard
aInternalGuard(GetMutex());
1569 ::sal_Int32 nHeight
= static_cast< ::sal_Int32
>(
1570 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1571 // XXX numeric overflow
1572 if (nHeight
!= m_nViewHeight
)
1574 m_nViewHeight
= nHeight
;
1576 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
1577 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1579 determineVisibleRange();
1581 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
1582 m_xParagraphs
->end());
1586 case VCLEVENT_WINDOW_GETFOCUS
:
1588 ::osl::MutexGuard
aInternalGuard(GetMutex());
1592 if (m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
1594 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1595 getParagraph(m_aFocused
));
1596 if (xParagraph
.is())
1597 xParagraph
->notifyEvent(
1598 ::css::accessibility::AccessibleEventId::
1601 ::css::uno::makeAny(
1602 ::css::accessibility::AccessibleStateType::
1607 case VCLEVENT_WINDOW_LOSEFOCUS
:
1609 ::osl::MutexGuard
aInternalGuard(GetMutex());
1613 if (m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
1615 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1616 getParagraph(m_aFocused
));
1617 if (xParagraph
.is())
1618 xParagraph
->notifyEvent(
1619 ::css::accessibility::AccessibleEventId::
1621 ::css::uno::makeAny(
1622 ::css::accessibility::AccessibleStateType::
1632 void Document::init()
1634 if (m_xParagraphs
.get() == 0)
1636 ::sal_uLong nCount
= m_rEngine
.GetParagraphCount();
1637 SAL_WNODEPRECATED_DECLARATIONS_PUSH
1638 ::std::auto_ptr
< Paragraphs
> p(new Paragraphs
);
1639 SAL_WNODEPRECATED_DECLARATIONS_POP
1640 p
->reserve(static_cast< Paragraphs::size_type
>(nCount
));
1641 // numeric overflow is harmless here
1642 for (::sal_uLong i
= 0; i
< nCount
; ++i
)
1643 p
->push_back(ParagraphInfo(static_cast< ::sal_Int32
>(
1644 m_rEngine
.GetTextHeight(i
))));
1645 // XXX numeric overflow
1646 m_nViewOffset
= static_cast< ::sal_Int32
>(
1647 m_rView
.GetStartDocPos().Y()); // XXX numeric overflow
1648 m_nViewHeight
= static_cast< ::sal_Int32
>(
1649 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1650 // XXX numeric overflow
1652 determineVisibleRange();
1653 m_nSelectionFirstPara
= -1;
1654 m_nSelectionFirstPos
= -1;
1655 m_nSelectionLastPara
= -1;
1656 m_nSelectionLastPos
= -1;
1657 m_aFocused
= m_xParagraphs
->end();
1658 m_bSelectionChangedNotification
= false;
1659 m_aEngineListener
.startListening(m_rEngine
);
1660 m_aViewListener
.startListening(*m_rView
.GetWindow());
1664 ::rtl::Reference
< ParagraphImpl
>
1665 Document::getParagraph(Paragraphs::iterator
const & rIt
)
1667 return static_cast< ParagraphImpl
* >(
1668 ::css::uno::Reference
< ::css::accessibility::XAccessible
>(
1669 rIt
->getParagraph()).get());
1672 ::css::uno::Reference
< ::css::accessibility::XAccessible
>
1673 Document::getAccessibleChild(Paragraphs::iterator
const & rIt
)
1675 ::css::uno::Reference
< ::css::accessibility::XAccessible
> xParagraph(
1676 rIt
->getParagraph());
1677 if (!xParagraph
.is())
1679 xParagraph
= new Paragraph(this, rIt
- m_xParagraphs
->begin());
1680 rIt
->setParagraph(xParagraph
);
1685 void Document::determineVisibleRange()
1687 Paragraphs::iterator
const aEnd
= m_xParagraphs
->end();
1689 m_aVisibleBegin
= aEnd
;
1690 m_aVisibleEnd
= aEnd
;
1691 m_nVisibleBeginOffset
= 0;
1693 ::sal_Int32 nPos
= 0;
1694 for (Paragraphs::iterator aIt
= m_xParagraphs
->begin(); m_aVisibleEnd
== aEnd
&& aIt
!= aEnd
; ++aIt
)
1696 ::sal_Int32
const nOldPos
= nPos
;
1697 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1698 if (m_aVisibleBegin
== aEnd
)
1700 if (nPos
>= m_nViewOffset
)
1702 m_aVisibleBegin
= aIt
;
1703 m_nVisibleBeginOffset
= m_nViewOffset
- nOldPos
;
1708 if (nPos
>= m_nViewOffset
+ m_nViewHeight
) // XXX numeric overflow
1710 m_aVisibleEnd
= aIt
;
1716 (m_aVisibleBegin
== m_xParagraphs
->end() && m_aVisibleEnd
== m_xParagraphs
->end() && m_nVisibleBeginOffset
== 0)
1717 || (m_aVisibleBegin
< m_aVisibleEnd
&& m_nVisibleBeginOffset
>= 0),
1718 "invalid visible range");
1721 void Document::notifyVisibleRangeChanges(
1722 Paragraphs::iterator
const & rOldVisibleBegin
,
1723 Paragraphs::iterator
const & rOldVisibleEnd
,
1724 Paragraphs::iterator
const & rInserted
)
1726 // XXX Replace this code that determines which paragraphs have changed from
1727 // invisible to visible or vice versa with a better algorithm.
1728 {for (Paragraphs::iterator
aIt(rOldVisibleBegin
); aIt
!= rOldVisibleEnd
;
1730 if (aIt
!= rInserted
1731 && (aIt
< m_aVisibleBegin
|| aIt
>= m_aVisibleEnd
))
1732 NotifyAccessibleEvent(
1733 ::css::accessibility::AccessibleEventId::
1735 ::css::uno::makeAny(getAccessibleChild(aIt
)),
1738 {for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1740 if (aIt
== rInserted
1741 || aIt
< rOldVisibleBegin
|| aIt
>= rOldVisibleEnd
)
1742 NotifyAccessibleEvent(
1743 ::css::accessibility::AccessibleEventId::
1746 ::css::uno::makeAny(getAccessibleChild(aIt
)));
1751 Document::changeParagraphText(::sal_uLong nNumber
, ::sal_uInt16 nBegin
, ::sal_uInt16 nEnd
,
1752 bool bCut
, bool bPaste
,
1753 OUString
const & rText
)
1755 m_rView
.SetSelection(::TextSelection(::TextPaM(nNumber
, nBegin
),
1756 ::TextPaM(nNumber
, nEnd
)));
1759 else if (nBegin
!= nEnd
)
1760 m_rView
.DeleteSelected();
1763 else if (!rText
.isEmpty())
1764 m_rView
.InsertText(rText
);
1767 void Document::handleParagraphNotifications()
1769 while (!m_aParagraphNotifications
.empty())
1771 ::TextHint
aHint(m_aParagraphNotifications
.front());
1772 m_aParagraphNotifications
.pop();
1773 switch (aHint
.GetId())
1775 case TEXT_HINT_PARAINSERTED
:
1777 ::sal_uLong n
= aHint
.GetValue();
1778 OSL_ENSURE(n
<= m_xParagraphs
->size(),
1779 "bad TEXT_HINT_PARAINSERTED event");
1781 // Save the values of old iterators (the iterators themselves
1782 // will get invalidated), and adjust the old values so that they
1783 // reflect the insertion of the new paragraph:
1784 Paragraphs::size_type nOldVisibleBegin
1785 = m_aVisibleBegin
- m_xParagraphs
->begin();
1786 Paragraphs::size_type nOldVisibleEnd
1787 = m_aVisibleEnd
- m_xParagraphs
->begin();
1788 Paragraphs::size_type nOldFocused
1789 = m_aFocused
- m_xParagraphs
->begin();
1790 if (n
<= nOldVisibleBegin
)
1791 ++nOldVisibleBegin
; // XXX numeric overflow
1792 if (n
<= nOldVisibleEnd
)
1793 ++nOldVisibleEnd
; // XXX numeric overflow
1794 if (n
<= nOldFocused
)
1795 ++nOldFocused
; // XXX numeric overflow
1796 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionFirstPara
)
1797 ++m_nSelectionFirstPara
; // XXX numeric overflow
1798 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionLastPara
)
1799 ++m_nSelectionLastPara
; // XXX numeric overflow
1801 Paragraphs::iterator
aIns(
1802 m_xParagraphs
->insert(
1803 m_xParagraphs
->begin() + n
,
1804 ParagraphInfo(static_cast< ::sal_Int32
>(
1805 m_rEngine
.GetTextHeight(n
)))));
1806 // XXX numeric overflow (2x)
1808 determineVisibleRange();
1809 m_aFocused
= m_xParagraphs
->begin() + nOldFocused
;
1811 for (Paragraphs::iterator
aIt(aIns
);;)
1814 if (aIt
== m_xParagraphs
->end())
1816 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1818 if (xParagraph
.is())
1819 xParagraph
->numberChanged(true);
1822 notifyVisibleRangeChanges(
1823 m_xParagraphs
->begin() + nOldVisibleBegin
,
1824 m_xParagraphs
->begin() + nOldVisibleEnd
, aIns
);
1827 case TEXT_HINT_PARAREMOVED
:
1829 ::sal_uLong n
= aHint
.GetValue();
1830 if (n
== TEXT_PARA_ALL
)
1832 {for (Paragraphs::iterator
aIt(m_aVisibleBegin
);
1833 aIt
!= m_aVisibleEnd
; ++aIt
)
1834 NotifyAccessibleEvent(
1835 ::css::accessibility::AccessibleEventId::
1837 ::css::uno::makeAny(getAccessibleChild(aIt
)),
1840 disposeParagraphs();
1841 m_xParagraphs
->clear();
1842 determineVisibleRange();
1843 m_nSelectionFirstPara
= -1;
1844 m_nSelectionFirstPos
= -1;
1845 m_nSelectionLastPara
= -1;
1846 m_nSelectionLastPos
= -1;
1847 m_aFocused
= m_xParagraphs
->end();
1851 OSL_ENSURE(n
< m_xParagraphs
->size(),
1852 "Bad TEXT_HINT_PARAREMOVED event");
1854 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
1855 // numeric overflow cannot occur
1857 // Save the values of old iterators (the iterators
1858 // themselves will get invalidated), and adjust the old
1859 // values so that they reflect the removal of the paragraph:
1860 Paragraphs::size_type nOldVisibleBegin
1861 = m_aVisibleBegin
- m_xParagraphs
->begin();
1862 Paragraphs::size_type nOldVisibleEnd
1863 = m_aVisibleEnd
- m_xParagraphs
->begin();
1865 = nOldVisibleBegin
<= n
&& n
< nOldVisibleEnd
;
1866 Paragraphs::size_type nOldFocused
1867 = m_aFocused
- m_xParagraphs
->begin();
1868 bool bWasFocused
= aIt
== m_aFocused
;
1869 if (n
< nOldVisibleBegin
)
1871 if (n
< nOldVisibleEnd
)
1873 if (n
< nOldFocused
)
1875 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionFirstPara
)
1876 --m_nSelectionFirstPara
;
1877 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionFirstPara
)
1879 if (m_nSelectionFirstPara
== m_nSelectionLastPara
)
1881 m_nSelectionFirstPara
= -1;
1882 m_nSelectionFirstPos
= -1;
1883 m_nSelectionLastPara
= -1;
1884 m_nSelectionLastPos
= -1;
1888 ++m_nSelectionFirstPara
;
1889 m_nSelectionFirstPos
= 0;
1892 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionLastPara
)
1893 --m_nSelectionLastPara
;
1894 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionLastPara
)
1896 OSL_ENSURE(m_nSelectionFirstPara
< m_nSelectionLastPara
,
1898 --m_nSelectionLastPara
;
1899 m_nSelectionLastPos
= 0x7FFFFFFF;
1902 ::css::uno::Reference
< ::css::accessibility::XAccessible
>
1905 xStrong
= getAccessibleChild(aIt
);
1906 ::css::uno::WeakReference
<
1907 ::css::accessibility::XAccessible
> xWeak(
1908 aIt
->getParagraph());
1909 aIt
= m_xParagraphs
->erase(aIt
);
1911 determineVisibleRange();
1912 m_aFocused
= bWasFocused
? m_xParagraphs
->end()
1913 : m_xParagraphs
->begin() + nOldFocused
;
1915 for (; aIt
!= m_xParagraphs
->end(); ++aIt
)
1917 ::rtl::Reference
< ParagraphImpl
> xParagraph(
1919 if (xParagraph
.is())
1920 xParagraph
->numberChanged(false);
1924 NotifyAccessibleEvent(
1925 ::css::accessibility::AccessibleEventId::
1927 ::css::uno::makeAny(xStrong
),
1930 ::css::uno::Reference
< ::css::lang::XComponent
> xComponent(
1931 xWeak
.get(), ::css::uno::UNO_QUERY
);
1932 if (xComponent
.is())
1933 xComponent
->dispose();
1935 notifyVisibleRangeChanges(
1936 m_xParagraphs
->begin() + nOldVisibleBegin
,
1937 m_xParagraphs
->begin() + nOldVisibleEnd
,
1938 m_xParagraphs
->end());
1942 case TEXT_HINT_FORMATPARA
:
1944 ::sal_uLong n
= aHint
.GetValue();
1945 OSL_ENSURE(n
< m_xParagraphs
->size(),
1946 "Bad TEXT_HINT_FORMATPARA event");
1948 (*m_xParagraphs
)[static_cast< Paragraphs::size_type
>(n
)].
1949 changeHeight(static_cast< ::sal_Int32
>(
1950 m_rEngine
.GetTextHeight(n
)));
1951 // XXX numeric overflow
1952 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
1953 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1954 determineVisibleRange();
1955 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
1956 m_xParagraphs
->end());
1958 if (n
< m_xParagraphs
->size())
1960 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
1961 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(aIt
));
1962 if (xParagraph
.is())
1963 xParagraph
->textChanged();
1968 OSL_FAIL( "bad buffered hint");
1972 if (m_bSelectionChangedNotification
)
1974 m_bSelectionChangedNotification
= false;
1975 handleSelectionChangeNotification();
1979 void Document::handleSelectionChangeNotification()
1981 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
1982 OSL_ENSURE(rSelection
.GetStart().GetPara() < m_xParagraphs
->size()
1983 && rSelection
.GetEnd().GetPara() < m_xParagraphs
->size(),
1984 "bad TEXT_HINT_VIEWSELECTIONCHANGED event");
1985 ::sal_Int32 nNewFirstPara
1986 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetPara());
1987 ::sal_Int32 nNewFirstPos
1988 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetIndex());
1989 // XXX numeric overflow
1990 ::sal_Int32 nNewLastPara
1991 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetPara());
1992 ::sal_Int32 nNewLastPos
1993 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetIndex());
1994 // XXX numeric overflow
1997 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + nNewLastPara
);
1998 if (m_aFocused
!= m_xParagraphs
->end() && m_aFocused
!= aIt
1999 && m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
2001 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(m_aFocused
));
2002 if (xParagraph
.is())
2003 xParagraph
->notifyEvent(
2004 ::css::accessibility::AccessibleEventId::
2006 ::css::uno::makeAny(
2007 ::css::accessibility::AccessibleStateType::FOCUSED
),
2011 // Gain focus and update cursor position:
2012 if (aIt
>= m_aVisibleBegin
&& aIt
< m_aVisibleEnd
2013 && (aIt
!= m_aFocused
2014 || nNewLastPara
!= m_nSelectionLastPara
2015 || nNewLastPos
!= m_nSelectionLastPos
))
2017 ::rtl::Reference
< ParagraphImpl
> xParagraph(getParagraph(aIt
));
2018 if (xParagraph
.is())
2020 if (aIt
!= m_aFocused
)
2021 xParagraph
->notifyEvent(
2022 ::css::accessibility::AccessibleEventId::
2025 ::css::uno::makeAny(
2026 ::css::accessibility::AccessibleStateType::FOCUSED
));
2027 if (nNewLastPara
!= m_nSelectionLastPara
2028 || nNewLastPos
!= m_nSelectionLastPos
)
2029 xParagraph
->notifyEvent(
2030 ::css::accessibility::AccessibleEventId::
2032 ::css::uno::makeAny
< ::sal_Int32
>(
2033 nNewLastPara
== m_nSelectionLastPara
2034 ? m_nSelectionLastPos
: 0),
2035 ::css::uno::makeAny(nNewLastPos
));
2040 // Update both old and new selection. (Regardless of how the two selections
2041 // look like, there will always be two ranges to the left and right of the
2042 // overlap---the overlap and/or the range to the right of it possibly being
2043 // empty. Only for these two ranges notifications have to be sent.)
2045 TextPaM
aOldTextStart( static_cast< sal_uLong
>( m_nSelectionFirstPara
), static_cast< sal_uInt16
>( m_nSelectionFirstPos
) );
2046 TextPaM
aOldTextEnd( static_cast< sal_uLong
>( m_nSelectionLastPara
), static_cast< sal_uInt16
>( m_nSelectionLastPos
) );
2047 TextPaM
aNewTextStart( static_cast< sal_uLong
>( nNewFirstPara
), static_cast< sal_uInt16
>( nNewFirstPos
) );
2048 TextPaM
aNewTextEnd( static_cast< sal_uLong
>( nNewLastPara
), static_cast< sal_uInt16
>( nNewLastPos
) );
2050 // justify selections
2051 justifySelection( aOldTextStart
, aOldTextEnd
);
2052 justifySelection( aNewTextStart
, aNewTextEnd
);
2059 if ( m_nSelectionFirstPara
== -1 )
2061 // old selection not initialized yet => notify events only for new selection (if not empty)
2062 nFirst1
= aNewTextStart
.GetPara();
2063 nLast1
= aNewTextEnd
.GetPara() + ( aNewTextStart
!= aNewTextEnd
? 1 : 0 );
2067 else if ( aOldTextStart
== aOldTextEnd
&& aNewTextStart
== aNewTextEnd
)
2069 // old and new selection empty => no events
2075 else if ( aOldTextStart
!= aOldTextEnd
&& aNewTextStart
== aNewTextEnd
)
2077 // old selection not empty + new selection empty => notify events only for old selection
2078 nFirst1
= aOldTextStart
.GetPara();
2079 nLast1
= aOldTextEnd
.GetPara() + 1;
2083 else if ( aOldTextStart
== aOldTextEnd
&& aNewTextStart
!= aNewTextEnd
)
2085 // old selection empty + new selection not empty => notify events only for new selection
2086 nFirst1
= aNewTextStart
.GetPara();
2087 nLast1
= aNewTextEnd
.GetPara() + 1;
2093 // old and new selection not empty => notify events for the two ranges left and right of the overlap
2094 ::std::vector
< TextPaM
> aTextPaMs(4);
2095 aTextPaMs
[0] = aOldTextStart
;
2096 aTextPaMs
[1] = aOldTextEnd
;
2097 aTextPaMs
[2] = aNewTextStart
;
2098 aTextPaMs
[3] = aNewTextEnd
;
2099 ::std::sort( aTextPaMs
.begin(), aTextPaMs
.end() );
2101 nFirst1
= aTextPaMs
[0].GetPara();
2102 nLast1
= aTextPaMs
[1].GetPara() + ( aTextPaMs
[0] != aTextPaMs
[1] ? 1 : 0 );
2104 nFirst2
= aTextPaMs
[2].GetPara();
2105 nLast2
= aTextPaMs
[3].GetPara() + ( aTextPaMs
[2] != aTextPaMs
[3] ? 1 : 0 );
2107 // adjust overlapping ranges
2108 if ( nLast1
> nFirst2
)
2112 // notify selection changes
2113 notifySelectionChange( nFirst1
, nLast1
);
2114 notifySelectionChange( nFirst2
, nLast2
);
2116 m_nSelectionFirstPara
= nNewFirstPara
;
2117 m_nSelectionFirstPos
= nNewFirstPos
;
2118 m_nSelectionLastPara
= nNewLastPara
;
2119 m_nSelectionLastPos
= nNewLastPos
;
2122 void Document::notifySelectionChange( sal_Int32 nFirst
, sal_Int32 nLast
)
2124 nFirst
= std::max( nFirst
, sal_Int32( 0 ) );
2125 nLast
= std::min( nLast
, sal_Int32( m_xParagraphs
->size() ) );
2126 Paragraphs::iterator
iFirst(m_xParagraphs
->begin() + nFirst
);
2127 Paragraphs::iterator
iLast(m_xParagraphs
->begin() + nLast
);
2128 if ( iFirst
< m_aVisibleBegin
)
2129 iFirst
= m_aVisibleBegin
;
2130 if ( iLast
> m_aVisibleEnd
)
2131 iLast
= m_aVisibleEnd
;
2132 if ( iFirst
< iLast
)
2134 for ( Paragraphs::iterator i
= iFirst
; i
!= iLast
; i
++ )
2136 ::rtl::Reference
< ParagraphImpl
> xParagraph( getParagraph( i
) );
2137 if ( xParagraph
.is() )
2139 xParagraph
->notifyEvent(
2140 ::css::accessibility::AccessibleEventId::SELECTION_CHANGED
,
2141 ::css::uno::Any(), ::css::uno::Any() );
2142 xParagraph
->notifyEvent(
2143 ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
,
2144 ::css::uno::Any(), ::css::uno::Any() );
2150 void Document::justifySelection( TextPaM
& rTextStart
, TextPaM
& rTextEnd
)
2152 if ( rTextStart
> rTextEnd
)
2154 TextPaM
aTextPaM( rTextStart
);
2155 rTextStart
= rTextEnd
;
2156 rTextEnd
= aTextPaM
;
2160 void Document::disposeParagraphs()
2162 for (Paragraphs::iterator
aIt(m_xParagraphs
->begin());
2163 aIt
!= m_xParagraphs
->end(); ++aIt
)
2165 ::css::uno::Reference
< ::css::lang::XComponent
> xComponent(
2166 aIt
->getParagraph().get(), ::css::uno::UNO_QUERY
);
2167 if (xComponent
.is())
2168 xComponent
->dispose();
2173 ::css::uno::Any
Document::mapFontColor(::Color
const & rColor
)
2175 return ::css::uno::makeAny(
2176 static_cast< ::sal_Int32
>(COLORDATA_RGB(rColor
.GetColor())));
2177 // FIXME keep transparency?
2181 ::Color
Document::mapFontColor(::css::uno::Any
const & rColor
)
2183 ::sal_Int32 nColor
= 0;
2185 return ::Color(static_cast< ::ColorData
>(nColor
));
2189 ::css::uno::Any
Document::mapFontWeight(::FontWeight nWeight
)
2191 // Map from ::FontWeight to ::css:awt::FontWeight, depends on order of
2192 // elements in ::FontWeight (vcl/vclenum.hxx):
2193 static float const aWeight
[]
2194 = { ::css::awt::FontWeight::DONTKNOW
, // WEIGHT_DONTKNOW
2195 ::css::awt::FontWeight::THIN
, // WEIGHT_THIN
2196 ::css::awt::FontWeight::ULTRALIGHT
, // WEIGHT_ULTRALIGHT
2197 ::css::awt::FontWeight::LIGHT
, // WEIGHT_LIGHT
2198 ::css::awt::FontWeight::SEMILIGHT
, // WEIGHT_SEMILIGHT
2199 ::css::awt::FontWeight::NORMAL
, // WEIGHT_NORMAL
2200 ::css::awt::FontWeight::NORMAL
, // WEIGHT_MEDIUM
2201 ::css::awt::FontWeight::SEMIBOLD
, // WEIGHT_SEMIBOLD
2202 ::css::awt::FontWeight::BOLD
, // WEIGHT_BOLD
2203 ::css::awt::FontWeight::ULTRABOLD
, // WEIGHT_ULTRABOLD
2204 ::css::awt::FontWeight::BLACK
}; // WEIGHT_BLACK
2205 return ::css::uno::makeAny(aWeight
[nWeight
]);
2209 ::FontWeight
Document::mapFontWeight(::css::uno::Any
const & rWeight
)
2211 float nWeight
= ::css::awt::FontWeight::NORMAL
;
2212 rWeight
>>= nWeight
;
2213 return nWeight
<= ::css::awt::FontWeight::DONTKNOW
? WEIGHT_DONTKNOW
2214 : nWeight
<= ::css::awt::FontWeight::THIN
? WEIGHT_THIN
2215 : nWeight
<= ::css::awt::FontWeight::ULTRALIGHT
? WEIGHT_ULTRALIGHT
2216 : nWeight
<= ::css::awt::FontWeight::LIGHT
? WEIGHT_LIGHT
2217 : nWeight
<= ::css::awt::FontWeight::SEMILIGHT
? WEIGHT_SEMILIGHT
2218 : nWeight
<= ::css::awt::FontWeight::NORMAL
? WEIGHT_NORMAL
2219 : nWeight
<= ::css::awt::FontWeight::SEMIBOLD
? WEIGHT_SEMIBOLD
2220 : nWeight
<= ::css::awt::FontWeight::BOLD
? WEIGHT_BOLD
2221 : nWeight
<= ::css::awt::FontWeight::ULTRABOLD
? WEIGHT_ULTRABOLD
2227 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */