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>
30 namespace accessibility
32 void SfxListenerGuard::startListening(::SfxBroadcaster
& rNotifier
)
34 OSL_ENSURE(m_pNotifier
== 0, "called more than once");
35 m_pNotifier
= &rNotifier
;
36 m_rListener
.StartListening(*m_pNotifier
, true);
39 void SfxListenerGuard::endListening()
43 m_rListener
.EndListening(*m_pNotifier
);
48 void WindowListenerGuard::startListening(vcl::Window
& rNotifier
)
50 OSL_ENSURE(m_pNotifier
== nullptr, "called more than once");
51 m_pNotifier
= &rNotifier
;
52 m_pNotifier
->AddEventListener(m_aListener
);
55 void WindowListenerGuard::endListening()
59 m_pNotifier
->RemoveEventListener(m_aListener
);
60 m_pNotifier
= nullptr;
64 Paragraph::Paragraph(::rtl::Reference
< Document
> const & rDocument
,
65 Paragraphs::size_type nNumber
):
66 ParagraphBase(m_aMutex
),
67 m_xDocument(rDocument
),
71 m_aParagraphText
= m_xDocument
->retrieveParagraphText(this);
75 Paragraph::numberChanged(bool bIncremented
)
83 void Paragraph::textChanged()
85 OUString aParagraphText
= implGetText();
86 css::uno::Any aOldValue
, aNewValue
;
87 if ( implInitTextChangedEvent( m_aParagraphText
, aParagraphText
, aOldValue
, aNewValue
) )
89 m_aParagraphText
= aParagraphText
;
90 notifyEvent(css::accessibility::AccessibleEventId::
92 aOldValue
, aNewValue
);
96 void Paragraph::notifyEvent(::sal_Int16 nEventId
,
97 css::uno::Any
const & rOldValue
,
98 css::uno::Any
const & rNewValue
)
101 comphelper::AccessibleEventNotifier::addEvent( m_nClientId
, css::accessibility::AccessibleEventObject(
102 static_cast< ::cppu::OWeakObject
* >(this),
103 nEventId
, rNewValue
, rOldValue
) );
107 css::uno::Reference
< css::accessibility::XAccessibleContext
> SAL_CALL
108 Paragraph::getAccessibleContext() throw (css::uno::RuntimeException
, std::exception
)
115 ::sal_Int32 SAL_CALL
Paragraph::getAccessibleChildCount()
116 throw (css::uno::RuntimeException
, std::exception
)
123 css::uno::Reference
< css::accessibility::XAccessible
> SAL_CALL
124 Paragraph::getAccessibleChild(::sal_Int32
)
125 throw (css::lang::IndexOutOfBoundsException
,
126 css::uno::RuntimeException
, std::exception
)
129 throw css::lang::IndexOutOfBoundsException(
130 "textwindowaccessibility.cxx:"
131 " Paragraph::getAccessibleChild",
132 static_cast< css::uno::XWeak
* >(this));
136 css::uno::Reference
< css::accessibility::XAccessible
> SAL_CALL
137 Paragraph::getAccessibleParent()
138 throw (css::uno::RuntimeException
, std::exception
)
141 return m_xDocument
->getAccessible();
145 ::sal_Int32 SAL_CALL
Paragraph::getAccessibleIndexInParent()
146 throw (css::uno::RuntimeException
, std::exception
)
149 return m_xDocument
->retrieveParagraphIndex(this);
153 ::sal_Int16 SAL_CALL
Paragraph::getAccessibleRole()
154 throw (css::uno::RuntimeException
, std::exception
)
157 return css::accessibility::AccessibleRole::PARAGRAPH
;
161 OUString SAL_CALL
Paragraph::getAccessibleDescription()
162 throw (css::uno::RuntimeException
, std::exception
)
169 OUString SAL_CALL
Paragraph::getAccessibleName()
170 throw (css::uno::RuntimeException
, std::exception
)
177 css::uno::Reference
< css::accessibility::XAccessibleRelationSet
>
178 SAL_CALL
Paragraph::getAccessibleRelationSet()
179 throw (css::uno::RuntimeException
, std::exception
)
182 return m_xDocument
->retrieveParagraphRelationSet( this );
186 css::uno::Reference
< css::accessibility::XAccessibleStateSet
>
187 SAL_CALL
Paragraph::getAccessibleStateSet()
188 throw (css::uno::RuntimeException
, std::exception
)
192 // FIXME Notification of changes (STATE_CHANGED) missing when
193 // m_rView.IsReadOnly() changes:
194 return new ::utl::AccessibleStateSetHelper(
195 m_xDocument
->retrieveParagraphState(this));
199 css::lang::Locale SAL_CALL
Paragraph::getLocale()
200 throw (css::accessibility::IllegalAccessibleComponentStateException
,
201 css::uno::RuntimeException
, std::exception
)
204 return m_xDocument
->retrieveLocale();
208 sal_Bool SAL_CALL
Paragraph::containsPoint(css::awt::Point
const & rPoint
)
209 throw (css::uno::RuntimeException
, std::exception
)
212 css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
214 return rPoint
.X
>= 0 && rPoint
.X
< aRect
.Width
215 && rPoint
.Y
>= 0 && rPoint
.Y
< aRect
.Height
;
219 css::uno::Reference
< css::accessibility::XAccessible
> SAL_CALL
220 Paragraph::getAccessibleAtPoint(css::awt::Point
const &)
221 throw (css::uno::RuntimeException
, std::exception
)
228 css::awt::Rectangle SAL_CALL
Paragraph::getBounds()
229 throw (css::uno::RuntimeException
, std::exception
)
232 return m_xDocument
->retrieveParagraphBounds(this, false);
236 css::awt::Point SAL_CALL
Paragraph::getLocation()
237 throw (css::uno::RuntimeException
, std::exception
)
240 css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
242 return css::awt::Point(aRect
.X
, aRect
.Y
);
246 css::awt::Point SAL_CALL
Paragraph::getLocationOnScreen()
247 throw (css::uno::RuntimeException
, std::exception
)
250 css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
252 return css::awt::Point(aRect
.X
, aRect
.Y
);
256 css::awt::Size SAL_CALL
Paragraph::getSize()
257 throw (css::uno::RuntimeException
, std::exception
)
260 css::awt::Rectangle
aRect(m_xDocument
->retrieveParagraphBounds(this,
262 return css::awt::Size(aRect
.Width
, aRect
.Height
);
266 void SAL_CALL
Paragraph::grabFocus() throw (css::uno::RuntimeException
, std::exception
)
269 vcl::Window
* pWindow
= m_xDocument
->GetWindow();
272 pWindow
->GrabFocus();
276 m_xDocument
->changeParagraphSelection(this, 0, 0);
278 catch (const css::lang::IndexOutOfBoundsException
& rEx
)
281 "textwindowaccessibility.cxx: Paragraph::grabFocus:"
282 " caught unexpected %s\n",
283 OUStringToOString(rEx
.Message
, RTL_TEXTENCODING_UTF8
).
289 css::util::Color SAL_CALL
Paragraph::getForeground()
290 throw (css::uno::RuntimeException
, std::exception
)
296 css::util::Color SAL_CALL
Paragraph::getBackground()
297 throw (css::uno::RuntimeException
, std::exception
)
303 ::sal_Int32 SAL_CALL
Paragraph::getCaretPosition()
304 throw (css::uno::RuntimeException
, std::exception
)
307 return m_xDocument
->retrieveParagraphCaretPosition(this);
311 sal_Bool SAL_CALL
Paragraph::setCaretPosition(::sal_Int32 nIndex
)
312 throw (css::lang::IndexOutOfBoundsException
,
313 css::uno::RuntimeException
, std::exception
)
316 m_xDocument
->changeParagraphSelection(this, nIndex
, nIndex
);
321 ::sal_Unicode SAL_CALL
Paragraph::getCharacter(::sal_Int32 nIndex
)
322 throw (css::lang::IndexOutOfBoundsException
,
323 css::uno::RuntimeException
, std::exception
)
326 return OCommonAccessibleText::getCharacter(nIndex
);
330 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
331 Paragraph::getCharacterAttributes(::sal_Int32 nIndex
, const ::com::sun::star::uno::Sequence
< OUString
>& aRequestedAttributes
)
332 throw (css::lang::IndexOutOfBoundsException
,
333 css::uno::RuntimeException
, std::exception
)
336 return m_xDocument
->retrieveCharacterAttributes( this, nIndex
, aRequestedAttributes
);
340 css::awt::Rectangle SAL_CALL
341 Paragraph::getCharacterBounds(::sal_Int32 nIndex
)
342 throw (css::lang::IndexOutOfBoundsException
,
343 css::uno::RuntimeException
, std::exception
)
346 css::awt::Rectangle
aBounds(m_xDocument
->retrieveCharacterBounds(this, nIndex
));
347 css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
348 aBounds
.X
-= aParaBounds
.X
;
349 aBounds
.Y
-= aParaBounds
.Y
;
354 ::sal_Int32 SAL_CALL
Paragraph::getCharacterCount()
355 throw (css::uno::RuntimeException
, std::exception
)
358 return OCommonAccessibleText::getCharacterCount();
363 Paragraph::getIndexAtPoint(css::awt::Point
const & rPoint
)
364 throw (css::uno::RuntimeException
, std::exception
)
367 css::awt::Point
aPoint(rPoint
);
368 css::awt::Rectangle
aParaBounds(m_xDocument
->retrieveParagraphBounds(this, false));
369 aPoint
.X
+= aParaBounds
.X
;
370 aPoint
.Y
+= aParaBounds
.Y
;
371 return m_xDocument
->retrieveCharacterIndex(this, aPoint
);
375 OUString SAL_CALL
Paragraph::getSelectedText()
376 throw (css::uno::RuntimeException
, std::exception
)
380 return OCommonAccessibleText::getSelectedText();
384 ::sal_Int32 SAL_CALL
Paragraph::getSelectionStart()
385 throw (css::uno::RuntimeException
, std::exception
)
388 return OCommonAccessibleText::getSelectionStart();
392 ::sal_Int32 SAL_CALL
Paragraph::getSelectionEnd()
393 throw (css::uno::RuntimeException
, std::exception
)
396 return OCommonAccessibleText::getSelectionEnd();
400 sal_Bool SAL_CALL
Paragraph::setSelection(::sal_Int32 nStartIndex
,
401 ::sal_Int32 nEndIndex
)
402 throw (css::lang::IndexOutOfBoundsException
,
403 css::uno::RuntimeException
, std::exception
)
406 m_xDocument
->changeParagraphSelection(this, nStartIndex
, nEndIndex
);
411 OUString SAL_CALL
Paragraph::getText()
412 throw (css::uno::RuntimeException
, std::exception
)
415 return OCommonAccessibleText::getText();
419 OUString SAL_CALL
Paragraph::getTextRange(::sal_Int32 nStartIndex
,
420 ::sal_Int32 nEndIndex
)
421 throw (css::lang::IndexOutOfBoundsException
,
422 css::uno::RuntimeException
, std::exception
)
425 return OCommonAccessibleText::getTextRange(nStartIndex
, nEndIndex
);
429 ::com::sun::star::accessibility::TextSegment SAL_CALL
Paragraph::getTextAtIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
432 return OCommonAccessibleText::getTextAtIndex(nIndex
, aTextType
);
436 ::com::sun::star::accessibility::TextSegment SAL_CALL
Paragraph::getTextBeforeIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
439 return OCommonAccessibleText::getTextBeforeIndex(nIndex
, aTextType
);
443 ::com::sun::star::accessibility::TextSegment SAL_CALL
Paragraph::getTextBehindIndex( sal_Int32 nIndex
, sal_Int16 aTextType
) throw (::com::sun::star::lang::IndexOutOfBoundsException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
446 return OCommonAccessibleText::getTextBehindIndex(nIndex
, aTextType
);
450 sal_Bool SAL_CALL
Paragraph::copyText(::sal_Int32 nStartIndex
,
451 ::sal_Int32 nEndIndex
)
452 throw (css::lang::IndexOutOfBoundsException
,
453 css::uno::RuntimeException
, std::exception
)
456 m_xDocument
->copyParagraphText(this, nStartIndex
, nEndIndex
);
461 sal_Bool SAL_CALL
Paragraph::cutText(::sal_Int32 nStartIndex
,
462 ::sal_Int32 nEndIndex
)
463 throw (css::lang::IndexOutOfBoundsException
,
464 css::uno::RuntimeException
, std::exception
)
467 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, true, false,
473 sal_Bool SAL_CALL
Paragraph::pasteText(::sal_Int32 nIndex
)
474 throw (css::lang::IndexOutOfBoundsException
,
475 css::uno::RuntimeException
, std::exception
)
478 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, true,
484 sal_Bool SAL_CALL
Paragraph::deleteText(::sal_Int32 nStartIndex
,
485 ::sal_Int32 nEndIndex
)
486 throw (css::lang::IndexOutOfBoundsException
,
487 css::uno::RuntimeException
, std::exception
)
490 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
496 sal_Bool SAL_CALL
Paragraph::insertText(OUString
const & rText
,
498 throw (css::lang::IndexOutOfBoundsException
,
499 css::uno::RuntimeException
, std::exception
)
502 m_xDocument
->changeParagraphText(this, nIndex
, nIndex
, false, false, rText
);
508 Paragraph::replaceText(::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
509 OUString
const & rReplacement
)
510 throw (css::lang::IndexOutOfBoundsException
,
511 css::uno::RuntimeException
, std::exception
)
514 m_xDocument
->changeParagraphText(this, nStartIndex
, nEndIndex
, false, false,
520 sal_Bool SAL_CALL
Paragraph::setAttributes(
521 ::sal_Int32 nStartIndex
, ::sal_Int32 nEndIndex
,
522 css::uno::Sequence
< css::beans::PropertyValue
> const & rAttributeSet
)
523 throw (css::lang::IndexOutOfBoundsException
,
524 css::uno::RuntimeException
, std::exception
)
527 m_xDocument
->changeParagraphAttributes(this, nStartIndex
, nEndIndex
,
533 sal_Bool SAL_CALL
Paragraph::setText(OUString
const & rText
)
534 throw (css::uno::RuntimeException
, std::exception
)
537 m_xDocument
->changeParagraphText(this, rText
);
542 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
543 Paragraph::getDefaultAttributes(const css::uno::Sequence
< OUString
>& RequestedAttributes
)
544 throw (css::uno::RuntimeException
, std::exception
)
547 return m_xDocument
->retrieveDefaultAttributes( this, RequestedAttributes
);
551 css::uno::Sequence
< css::beans::PropertyValue
> SAL_CALL
552 Paragraph::getRunAttributes(::sal_Int32 Index
, const css::uno::Sequence
< OUString
>& RequestedAttributes
)
553 throw (css::lang::IndexOutOfBoundsException
,
554 css::uno::RuntimeException
, std::exception
)
557 return m_xDocument
->retrieveRunAttributes( this, Index
, RequestedAttributes
);
561 ::sal_Int32 SAL_CALL
Paragraph::getLineNumberAtIndex( ::sal_Int32 nIndex
)
562 throw (css::lang::IndexOutOfBoundsException
,
563 css::uno::RuntimeException
, std::exception
)
567 ::sal_Int32 nLineNo
= -1;
568 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
, &nLineNo
);
574 css::accessibility::TextSegment SAL_CALL
Paragraph::getTextAtLineNumber( ::sal_Int32 nLineNo
)
575 throw (css::lang::IndexOutOfBoundsException
,
576 css::uno::RuntimeException
, std::exception
)
580 css::i18n::Boundary aBoundary
=
581 m_xDocument
->retrieveParagraphBoundaryOfLine( this, nLineNo
);
583 return css::accessibility::TextSegment( getTextRange(aBoundary
.startPos
, aBoundary
.endPos
),
584 aBoundary
.startPos
, aBoundary
.endPos
);
588 css::accessibility::TextSegment SAL_CALL
Paragraph::getTextAtLineWithCaret( )
589 throw (css::uno::RuntimeException
, std::exception
)
593 sal_Int32 nLineNo
= getNumberOfLineWithCaret();
596 return ( nLineNo
>= 0 ) ?
597 getTextAtLineNumber( nLineNo
) :
598 css::accessibility::TextSegment();
599 } catch (const css::lang::IndexOutOfBoundsException
&) {
600 throw css::uno::RuntimeException(
601 "textwindowaccessibility.cxx:"
602 " Paragraph::getTextAtLineWithCaret",
603 static_cast< css::uno::XWeak
* >( this ) );
608 ::sal_Int32 SAL_CALL
Paragraph::getNumberOfLineWithCaret( )
609 throw (css::uno::RuntimeException
, std::exception
)
612 return m_xDocument
->retrieveParagraphLineWithCursor(this);
617 void SAL_CALL
Paragraph::addAccessibleEventListener(
619 css::accessibility::XAccessibleEventListener
> const & rListener
)
620 throw (css::uno::RuntimeException
, std::exception
)
624 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
625 if (rBHelper
.bDisposed
|| rBHelper
.bInDispose
)
628 rListener
->disposing(css::lang::EventObject(
629 static_cast< ::cppu::OWeakObject
* >(this)));
634 m_nClientId
= comphelper::AccessibleEventNotifier::registerClient( );
635 comphelper::AccessibleEventNotifier::addEventListener( m_nClientId
, rListener
);
641 void SAL_CALL
Paragraph::removeAccessibleEventListener(
643 css::accessibility::XAccessibleEventListener
> const & rListener
)
644 throw (css::uno::RuntimeException
, std::exception
)
646 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
648 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
649 if (rListener
.is() && m_nClientId
!= 0
650 && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId
, rListener
) == 0)
658 // no listeners anymore
659 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
660 // and at least to us not firing any events anymore, in case somebody calls
661 // NotifyAccessibleEvent, again
662 comphelper::AccessibleEventNotifier::revokeClient(nId
);
667 void SAL_CALL
Paragraph::disposing()
669 comphelper::AccessibleEventNotifier::TClientId nId
= 0;
671 ::osl::ClearableMutexGuard
aGuard(rBHelper
.rMutex
);
676 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId
, *this);
680 OUString
Paragraph::implGetText()
682 return m_xDocument
->retrieveParagraphText(this);
686 css::lang::Locale
Paragraph::implGetLocale()
688 return m_xDocument
->retrieveLocale();
692 void Paragraph::implGetSelection(::sal_Int32
& rStartIndex
,
693 ::sal_Int32
& rEndIndex
)
695 m_xDocument
->retrieveParagraphSelection(this, &rStartIndex
, &rEndIndex
);
699 void Paragraph::implGetParagraphBoundary( css::i18n::Boundary
& rBoundary
,
702 OUString
sText( implGetText() );
703 ::sal_Int32 nLength
= sText
.getLength();
705 if ( implIsValidIndex( nIndex
, nLength
) )
707 rBoundary
.startPos
= 0;
708 rBoundary
.endPos
= nLength
;
712 rBoundary
.startPos
= nIndex
;
713 rBoundary
.endPos
= nIndex
;
718 void Paragraph::implGetLineBoundary( css::i18n::Boundary
& rBoundary
,
721 OUString
sText( implGetText() );
722 ::sal_Int32 nLength
= sText
.getLength();
724 if ( implIsValidIndex( nIndex
, nLength
) || nIndex
== nLength
)
726 css::i18n::Boundary aBoundary
=
727 m_xDocument
->retrieveParagraphLineBoundary( this, nIndex
);
728 rBoundary
.startPos
= aBoundary
.startPos
;
729 rBoundary
.endPos
= aBoundary
.endPos
;
733 rBoundary
.startPos
= nIndex
;
734 rBoundary
.endPos
= nIndex
;
739 void Paragraph::checkDisposed()
741 ::osl::MutexGuard
aGuard(rBHelper
.rMutex
);
742 if (!(rBHelper
.bDisposed
|| rBHelper
.bInDispose
))
744 throw css::lang::DisposedException(
745 OUString(), static_cast< css::uno::XWeak
* >(this));
748 Document::Document(::VCLXWindow
* pVclXWindow
, ::TextEngine
& rEngine
,
750 VCLXAccessibleComponent(pVclXWindow
),
751 m_xAccessible(pVclXWindow
),
754 m_aEngineListener(*this),
755 m_aViewListener(LINK(this, Document
, WindowEventHandler
)),
758 m_nVisibleBeginOffset(0),
759 m_nSelectionFirstPara(-1),
760 m_nSelectionFirstPos(-1),
761 m_nSelectionLastPara(-1),
762 m_nSelectionLastPos(-1),
763 m_bSelectionChangedNotification(false)
766 css::lang::Locale
Document::retrieveLocale()
768 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
769 return m_rEngine
.GetLocale();
772 ::sal_Int32
Document::retrieveParagraphIndex(Paragraph
const * pParagraph
)
774 ::osl::MutexGuard
aInternalGuard(GetMutex());
776 // If a client holds on to a Paragraph that is no longer visible, it can
777 // happen that this Paragraph lies outside the range from m_aVisibleBegin
778 // to m_aVisibleEnd. In that case, return -1 instead of a valid index:
779 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
780 + pParagraph
->getNumber());
781 return aPara
< m_aVisibleBegin
|| aPara
>= m_aVisibleEnd
782 ? -1 : static_cast< ::sal_Int32
>(aPara
- m_aVisibleBegin
);
783 // XXX numeric overflow
786 ::sal_Int64
Document::retrieveParagraphState(Paragraph
const * pParagraph
)
788 ::osl::MutexGuard
aInternalGuard(GetMutex());
790 // If a client holds on to a Paragraph that is no longer visible, it can
791 // happen that this Paragraph lies outside the range from m_aVisibleBegin
792 // to m_aVisibleEnd. In that case, it is neither VISIBLE nor SHOWING:
794 = (static_cast< ::sal_Int64
>(1)
795 << css::accessibility::AccessibleStateType::ENABLED
)
796 | (static_cast< ::sal_Int64
>(1)
797 << css::accessibility::AccessibleStateType::SENSITIVE
)
798 | (static_cast< ::sal_Int64
>(1)
799 << css::accessibility::AccessibleStateType::FOCUSABLE
)
800 | (static_cast< ::sal_Int64
>(1)
801 << css::accessibility::AccessibleStateType::MULTI_LINE
);
802 if (!m_rView
.IsReadOnly())
803 nState
|= (static_cast< ::sal_Int64
>(1)
804 << css::accessibility::AccessibleStateType::EDITABLE
);
805 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
806 + pParagraph
->getNumber());
807 if (aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
810 |= (static_cast< ::sal_Int64
>(1)
811 << css::accessibility::AccessibleStateType::VISIBLE
)
812 | (static_cast< ::sal_Int64
>(1)
813 << css::accessibility::AccessibleStateType::SHOWING
);
814 if (aPara
== m_aFocused
)
815 nState
|= (static_cast< ::sal_Int64
>(1)
816 << css::accessibility::AccessibleStateType::FOCUSED
);
822 Document::retrieveParagraphBounds(Paragraph
const * pParagraph
,
825 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
826 ::osl::MutexGuard
aInternalGuard(GetMutex());
828 // If a client holds on to a Paragraph that is no longer visible (as it
829 // scrolled out the top of the view), it can happen that this Paragraph
830 // lies before m_aVisibleBegin. In that case, calculate the vertical
831 // position of the Paragraph starting at paragraph 0, otherwise optimize
832 // and start at m_aVisibleBegin:
833 Paragraphs::iterator
aPara(m_xParagraphs
->begin()
834 + pParagraph
->getNumber());
836 Paragraphs::iterator aIt
;
837 if (aPara
< m_aVisibleBegin
)
840 aIt
= m_xParagraphs
->begin();
844 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
845 aIt
= m_aVisibleBegin
;
847 for (; aIt
!= aPara
; ++aIt
)
848 nPos
+= aIt
->getHeight();
852 aOrig
= m_rView
.GetWindow()->OutputToAbsoluteScreenPixel(aOrig
);
854 return css::awt::Rectangle(
855 static_cast< ::sal_Int32
>(aOrig
.X()),
856 static_cast< ::sal_Int32
>(aOrig
.Y()) + nPos
- m_nViewOffset
,
857 m_rView
.GetWindow()->GetOutputSizePixel().Width(), aPara
->getHeight());
858 // XXX numeric overflow (3x)
862 Document::retrieveParagraphText(Paragraph
const * pParagraph
)
864 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
865 ::osl::MutexGuard
aInternalGuard(GetMutex());
866 return m_rEngine
.GetText(static_cast< ::sal_uLong
>(pParagraph
->getNumber()));
867 // numeric overflow cannot happen here
870 void Document::retrieveParagraphSelection(Paragraph
const * pParagraph
,
871 ::sal_Int32
* pBegin
,
874 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
875 ::osl::MutexGuard
aInternalGuard(GetMutex());
876 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
877 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
878 TextPaM
aStartPaM( rSelection
.GetStart() );
879 TextPaM
aEndPaM( rSelection
.GetEnd() );
880 TextPaM
aMinPaM( ::std::min( aStartPaM
, aEndPaM
) );
881 TextPaM
aMaxPaM( ::std::max( aStartPaM
, aEndPaM
) );
883 if ( nNumber
>= aMinPaM
.GetPara() && nNumber
<= aMaxPaM
.GetPara() )
885 *pBegin
= nNumber
> aMinPaM
.GetPara()
887 : static_cast< ::sal_Int32
>( aMinPaM
.GetIndex() );
888 // XXX numeric overflow
889 *pEnd
= nNumber
< aMaxPaM
.GetPara()
890 ? static_cast< ::sal_Int32
>( m_rEngine
.GetText(static_cast< ::sal_uLong
>(nNumber
)).getLength() )
891 : static_cast< ::sal_Int32
>( aMaxPaM
.GetIndex() );
892 // XXX numeric overflow (3x)
894 if ( aStartPaM
> aEndPaM
)
895 ::std::swap( *pBegin
, *pEnd
);
904 ::sal_Int32
Document::retrieveParagraphCaretPosition(Paragraph
const * pParagraph
)
906 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
907 ::osl::MutexGuard
aInternalGuard(GetMutex());
908 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
909 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
910 TextPaM
aEndPaM( rSelection
.GetEnd() );
912 return aEndPaM
.GetPara() == nNumber
913 ? static_cast< ::sal_Int32
>(aEndPaM
.GetIndex()) : -1;
917 Document::retrieveCharacterBounds(Paragraph
const * pParagraph
,
920 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
921 ::osl::MutexGuard
aInternalGuard(GetMutex());
922 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
923 sal_Int32 nLength
= m_rEngine
.GetText(nNumber
).getLength();
924 // XXX numeric overflow
925 if (nIndex
< 0 || nIndex
> nLength
)
926 throw css::lang::IndexOutOfBoundsException(
927 "textwindowaccessibility.cxx:"
928 " Document::retrieveCharacterAttributes",
929 static_cast< css::uno::XWeak
* >(this));
930 css::awt::Rectangle
aBounds( 0, 0, 0, 0 );
931 if ( nIndex
== nLength
)
933 aBounds
= AWTRectangle(
934 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
935 static_cast< ::sal_uInt16
>(nIndex
))));
940 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
941 static_cast< ::sal_uInt16
>(nIndex
))));
942 // XXX numeric overflow
944 m_rEngine
.PaMtoEditCursor(::TextPaM(nNumber
,
945 static_cast< ::sal_uInt16
>(nIndex
)
947 // XXX numeric overflow (2x)
948 // FIXME If the vertical extends of the two cursors do not match, assume
949 // nIndex is the last character on the line; the bounding box will then
950 // extend to m_rEnginge.GetMaxTextWidth():
951 ::sal_Int32 nWidth
= (aLeft
.Top() == aRight
.Top()
952 && aLeft
.Bottom() == aRight
.Bottom())
953 ? static_cast< ::sal_Int32
>(aRight
.Left() - aLeft
.Left())
954 : static_cast< ::sal_Int32
>(m_rEngine
.GetMaxTextWidth()
956 // XXX numeric overflow (4x)
957 aBounds
= css::awt::Rectangle(static_cast< ::sal_Int32
>(aLeft
.Left()),
958 static_cast< ::sal_Int32
>(aLeft
.Top() - m_nViewOffset
),
960 static_cast< ::sal_Int32
>(aLeft
.Bottom()
962 // XXX numeric overflow (4x)
967 ::sal_Int32
Document::retrieveCharacterIndex(Paragraph
const * pParagraph
,
968 css::awt::Point
const & rPoint
)
970 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
971 ::osl::MutexGuard
aInternalGuard(GetMutex());
972 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
973 // XXX numeric overflow
974 ::TextPaM
aPaM(m_rEngine
.GetPaM(::Point(static_cast< long >(rPoint
.X
),
975 static_cast< long >(rPoint
.Y
))));
976 // XXX numeric overflow (2x)
977 return aPaM
.GetPara() == nNumber
978 ? static_cast< ::sal_Int32
>(aPaM
.GetIndex()) : -1;
979 // XXX numeric overflow
984 const css::beans::PropertyValue
* pValues
;
985 explicit IndexCompare(const css::beans::PropertyValue
* pVals
)
989 bool operator() ( const sal_Int32
& a
, const sal_Int32
& b
) const
991 return pValues
[a
].Name
< pValues
[b
].Name
;
995 css::uno::Sequence
< css::beans::PropertyValue
>
996 Document::retrieveCharacterAttributes(
997 Paragraph
const * pParagraph
, ::sal_Int32 nIndex
,
998 const css::uno::Sequence
< OUString
>& aRequestedAttributes
)
1000 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1002 vcl::Font aFont
= m_rEngine
.GetFont();
1003 const sal_Int32 AttributeCount
= 9;
1005 css::uno::Sequence
< css::beans::PropertyValue
> aAttribs( AttributeCount
);
1007 //character background color
1008 aAttribs
[i
].Name
= "CharBackColor";
1009 aAttribs
[i
].Handle
= -1;
1010 aAttribs
[i
].Value
= mapFontColor( aFont
.GetFillColor() );
1011 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1015 aAttribs
[i
].Name
= "CharColor";
1016 aAttribs
[i
].Handle
= -1;
1017 //aAttribs[i].Value = mapFontColor( aFont.GetColor() );
1018 aAttribs
[i
].Value
= mapFontColor( m_rEngine
.GetTextColor() );
1019 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1022 //character font name
1023 aAttribs
[i
].Name
= "CharFontName";
1024 aAttribs
[i
].Handle
= -1;
1025 aAttribs
[i
].Value
= css::uno::makeAny( aFont
.GetName() );
1026 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1030 aAttribs
[i
].Name
= "CharHeight";
1031 aAttribs
[i
].Handle
= -1;
1032 aAttribs
[i
].Value
= css::uno::makeAny( (sal_Int16
)aFont
.GetHeight() );
1033 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1037 aAttribs
[i
].Name
= "CharPosture";
1038 aAttribs
[i
].Handle
= -1;
1039 aAttribs
[i
].Value
= css::uno::makeAny( (sal_Int16
)aFont
.GetItalic() );
1040 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1045 aAttribs[i].Name = "CharRelief";
1046 aAttribs[i].Handle = -1;
1047 aAttribs[i].Value = css::uno::makeAny( (sal_Int16)aFont.GetRelief() );
1048 aAttribs[i].State = css::beans::PropertyState_DIRECT_VALUE;
1052 //character strikeout
1053 aAttribs
[i
].Name
= "CharStrikeout";
1054 aAttribs
[i
].Handle
= -1;
1055 aAttribs
[i
].Value
= css::uno::makeAny( (sal_Int16
)aFont
.GetStrikeout() );
1056 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1059 //character underline
1060 aAttribs
[i
].Name
= "CharUnderline";
1061 aAttribs
[i
].Handle
= -1;
1062 aAttribs
[i
].Value
= css::uno::makeAny( (sal_Int16
)aFont
.GetUnderline() );
1063 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1067 aAttribs
[i
].Name
= "CharWeight";
1068 aAttribs
[i
].Handle
= -1;
1069 aAttribs
[i
].Value
= css::uno::makeAny( (float)aFont
.GetWeight() );
1070 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1073 //character alignment
1074 aAttribs
[i
].Name
= "ParaAdjust";
1075 aAttribs
[i
].Handle
= -1;
1076 aAttribs
[i
].Value
= css::uno::makeAny( (sal_Int16
)m_rEngine
.GetTextAlign() );
1077 aAttribs
[i
].State
= css::beans::PropertyState_DIRECT_VALUE
;
1080 ::osl::MutexGuard
aInternalGuard(GetMutex());
1081 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1082 // XXX numeric overflow
1083 // nIndex can be equal to getLength();
1084 if (nIndex
< 0 || nIndex
> m_rEngine
.GetText(nNumber
).getLength())
1085 throw css::lang::IndexOutOfBoundsException(
1086 "textwindowaccessibility.cxx:"
1087 " Document::retrieveCharacterAttributes",
1088 static_cast< css::uno::XWeak
* >(this));
1090 // retrieve default attributes
1091 tPropValMap aCharAttrSeq
;
1092 retrieveDefaultAttributesImpl( pParagraph
, aRequestedAttributes
, aCharAttrSeq
);
1094 // retrieve run attributes
1095 tPropValMap aRunAttrSeq
;
1096 retrieveRunAttributesImpl( pParagraph
, nIndex
, aRequestedAttributes
, aRunAttrSeq
);
1098 // merge default and run attributes
1099 for ( tPropValMap::const_iterator aRunIter
= aRunAttrSeq
.begin();
1100 aRunIter
!= aRunAttrSeq
.end();
1103 aCharAttrSeq
[ aRunIter
->first
] = aRunIter
->second
;
1106 css::beans::PropertyValue
* pValues
= aAttribs
.getArray();
1107 for (i
= 0; i
< AttributeCount
; i
++,pValues
++)
1109 aCharAttrSeq
[ pValues
->Name
] = *pValues
;
1112 css::uno::Sequence
< css::beans::PropertyValue
> aRes
= convertHashMapToSequence( aCharAttrSeq
);
1114 // sort the attributes
1115 sal_Int32 nLength
= aRes
.getLength();
1116 const css::beans::PropertyValue
* pPairs
= aRes
.getConstArray();
1117 sal_Int32
* pIndices
= new sal_Int32
[nLength
];
1118 for( i
= 0; i
< nLength
; i
++ )
1120 std::sort( &pIndices
[0], &pIndices
[nLength
], IndexCompare(pPairs
) );
1121 // create sorted sequences according to index array
1122 css::uno::Sequence
< css::beans::PropertyValue
> aNewValues( nLength
);
1123 css::beans::PropertyValue
* pNewValues
= aNewValues
.getArray();
1124 for( i
= 0; i
< nLength
; i
++ )
1126 pNewValues
[i
] = pPairs
[pIndices
[i
]];
1133 void Document::retrieveDefaultAttributesImpl(
1134 Paragraph
const * pParagraph
,
1135 const css::uno::Sequence
< OUString
>& RequestedAttributes
,
1136 tPropValMap
& rDefAttrSeq
)
1138 // default attributes are not supported by text engine
1140 (void) RequestedAttributes
;
1144 css::uno::Sequence
< css::beans::PropertyValue
>
1145 Document::retrieveDefaultAttributes(
1146 Paragraph
const * pParagraph
,
1147 const css::uno::Sequence
< OUString
>& RequestedAttributes
)
1149 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1150 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1152 tPropValMap aDefAttrSeq
;
1153 retrieveDefaultAttributesImpl( pParagraph
, RequestedAttributes
, aDefAttrSeq
);
1154 return convertHashMapToSequence( aDefAttrSeq
);
1158 css::uno::Sequence
< css::beans::PropertyValue
>
1159 Document::convertHashMapToSequence(tPropValMap
& rAttrSeq
)
1161 css::uno::Sequence
< css::beans::PropertyValue
> aValues( rAttrSeq
.size() );
1162 css::beans::PropertyValue
* pValues
= aValues
.getArray();
1164 for ( tPropValMap::const_iterator aIter
= rAttrSeq
.begin();
1165 aIter
!= rAttrSeq
.end();
1168 pValues
[i
] = aIter
->second
;
1174 void Document::retrieveRunAttributesImpl(
1175 Paragraph
const * pParagraph
, ::sal_Int32 Index
,
1176 const css::uno::Sequence
< OUString
>& RequestedAttributes
,
1177 tPropValMap
& rRunAttrSeq
)
1179 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1180 ::TextPaM
aPaM( nNumber
, static_cast< ::sal_uInt16
>( Index
) );
1181 // XXX numeric overflow
1182 // FIXME TEXTATTR_HYPERLINK ignored:
1183 ::TextAttribFontColor
const * pColor
1184 = static_cast< ::TextAttribFontColor
const * >(
1185 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTCOLOR
) );
1186 ::TextAttribFontWeight
const * pWeight
1187 = static_cast< ::TextAttribFontWeight
const * >(
1188 m_rEngine
.FindAttrib( aPaM
, TEXTATTR_FONTWEIGHT
) );
1189 tPropValMap aRunAttrSeq
;
1192 css::beans::PropertyValue aPropVal
;
1193 aPropVal
.Name
= "CharColor";
1194 aPropVal
.Handle
= -1;
1195 aPropVal
.Value
= mapFontColor( pColor
->GetColor() );
1196 aPropVal
.State
= css::beans::PropertyState_DIRECT_VALUE
;
1197 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1201 css::beans::PropertyValue aPropVal
;
1202 aPropVal
.Name
= "CharWeight";
1203 aPropVal
.Handle
= -1;
1204 aPropVal
.Value
= mapFontWeight( pWeight
->getFontWeight() );
1205 aPropVal
.State
= css::beans::PropertyState_DIRECT_VALUE
;
1206 aRunAttrSeq
[ aPropVal
.Name
] = aPropVal
;
1208 if ( RequestedAttributes
.getLength() == 0 )
1210 rRunAttrSeq
= aRunAttrSeq
;
1214 const OUString
* pReqAttrs
= RequestedAttributes
.getConstArray();
1215 const ::sal_Int32 nLength
= RequestedAttributes
.getLength();
1216 for ( ::sal_Int32 i
= 0; i
< nLength
; ++i
)
1218 tPropValMap::iterator aIter
= aRunAttrSeq
.find( pReqAttrs
[i
] );
1219 if ( aIter
!= aRunAttrSeq
.end() )
1221 rRunAttrSeq
[ (*aIter
).first
] = (*aIter
).second
;
1227 css::uno::Sequence
< css::beans::PropertyValue
>
1228 Document::retrieveRunAttributes(
1229 Paragraph
const * pParagraph
, ::sal_Int32 Index
,
1230 const css::uno::Sequence
< OUString
>& RequestedAttributes
)
1232 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1233 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1234 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1235 // XXX numeric overflow
1236 if ( Index
< 0 || Index
>= m_rEngine
.GetText(nNumber
).getLength() )
1237 throw css::lang::IndexOutOfBoundsException(
1238 "textwindowaccessibility.cxx:"
1239 " Document::retrieveRunAttributes",
1240 static_cast< css::uno::XWeak
* >( this ) );
1242 tPropValMap aRunAttrSeq
;
1243 retrieveRunAttributesImpl( pParagraph
, Index
, RequestedAttributes
, aRunAttrSeq
);
1244 return convertHashMapToSequence( aRunAttrSeq
);
1247 void Document::changeParagraphText(Paragraph
* pParagraph
,
1248 OUString
const & rText
)
1250 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1252 ::osl::MutexGuard
aInternalGuard(GetMutex());
1253 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1254 // XXX numeric overflow
1255 changeParagraphText(nNumber
, 0, m_rEngine
.GetTextLen(nNumber
), false,
1260 void Document::changeParagraphText(Paragraph
* pParagraph
,
1261 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1262 bool bCut
, bool bPaste
,
1263 OUString
const & rText
)
1265 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1267 ::osl::MutexGuard
aInternalGuard(GetMutex());
1268 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1269 // XXX numeric overflow
1270 if (nBegin
< 0 || nBegin
> nEnd
1271 || nEnd
> m_rEngine
.GetText(nNumber
).getLength())
1272 throw css::lang::IndexOutOfBoundsException(
1273 "textwindowaccessibility.cxx:"
1274 " Document::changeParagraphText",
1275 static_cast< css::uno::XWeak
* >(this));
1276 changeParagraphText(nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1277 static_cast< ::sal_uInt16
>(nEnd
), bCut
, bPaste
, rText
);
1278 // XXX numeric overflow (2x)
1282 void Document::copyParagraphText(Paragraph
const * pParagraph
,
1283 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1285 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1287 ::osl::MutexGuard
aInternalGuard(GetMutex());
1288 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1289 // XXX numeric overflow
1290 if (nBegin
< 0 || nBegin
> nEnd
1291 || nEnd
> m_rEngine
.GetText(nNumber
).getLength())
1292 throw css::lang::IndexOutOfBoundsException(
1293 "textwindowaccessibility.cxx:"
1294 " Document::copyParagraphText",
1295 static_cast< css::uno::XWeak
* >(this));
1296 m_rView
.SetSelection(
1297 ::TextSelection(::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nBegin
)),
1298 ::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nEnd
))));
1299 // XXX numeric overflow (2x)
1304 void Document::changeParagraphAttributes(
1305 Paragraph
* pParagraph
, ::sal_Int32 nBegin
, ::sal_Int32 nEnd
,
1306 css::uno::Sequence
< css::beans::PropertyValue
> const & rAttributeSet
)
1308 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1310 ::osl::MutexGuard
aInternalGuard(GetMutex());
1311 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1312 // XXX numeric overflow
1313 if (nBegin
< 0 || nBegin
> nEnd
1314 || nEnd
> m_rEngine
.GetText(nNumber
).getLength())
1315 throw css::lang::IndexOutOfBoundsException(
1316 "textwindowaccessibility.cxx:"
1317 " Document::changeParagraphAttributes",
1318 static_cast< css::uno::XWeak
* >(this));
1320 // FIXME The new attributes are added to any attributes already set,
1321 // they do not replace the old attributes as required by
1322 // XAccessibleEditableText.setAttributes:
1323 for (::sal_Int32 i
= 0; i
< rAttributeSet
.getLength(); ++i
)
1324 if ( rAttributeSet
[i
].Name
== "CharColor" )
1325 m_rEngine
.SetAttrib(::TextAttribFontColor(
1326 mapFontColor(rAttributeSet
[i
].Value
)),
1327 nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1328 static_cast< ::sal_uInt16
>(nEnd
));
1329 // XXX numeric overflow (2x)
1330 else if ( rAttributeSet
[i
].Name
== "CharWeight" )
1331 m_rEngine
.SetAttrib(::TextAttribFontWeight(
1332 mapFontWeight(rAttributeSet
[i
].Value
)),
1333 nNumber
, static_cast< ::sal_uInt16
>(nBegin
),
1334 static_cast< ::sal_uInt16
>(nEnd
));
1335 // XXX numeric overflow (2x)
1339 void Document::changeParagraphSelection(Paragraph
* pParagraph
,
1340 ::sal_Int32 nBegin
, ::sal_Int32 nEnd
)
1342 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1344 ::osl::MutexGuard
aInternalGuard(GetMutex());
1345 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>(pParagraph
->getNumber());
1346 // XXX numeric overflow
1347 if (nBegin
< 0 || nBegin
> nEnd
1348 || nEnd
> m_rEngine
.GetText(nNumber
).getLength())
1349 throw css::lang::IndexOutOfBoundsException(
1350 "textwindowaccessibility.cxx:"
1351 " Document::changeParagraphSelection",
1352 static_cast< css::uno::XWeak
* >(this));
1353 m_rView
.SetSelection(
1354 ::TextSelection(::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nBegin
)),
1355 ::TextPaM(nNumber
, static_cast< ::sal_uInt16
>(nEnd
))));
1356 // XXX numeric overflow (2x)
1361 Document::retrieveParagraphLineBoundary( Paragraph
const * pParagraph
,
1362 ::sal_Int32 nIndex
, ::sal_Int32
*pLineNo
)
1364 css::i18n::Boundary aBoundary
;
1365 aBoundary
.startPos
= nIndex
;
1366 aBoundary
.endPos
= nIndex
;
1368 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1370 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1371 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1372 if ( nIndex
< 0 || nIndex
> m_rEngine
.GetText( nNumber
).getLength() )
1373 throw css::lang::IndexOutOfBoundsException(
1374 "textwindowaccessibility.cxx:"
1375 " Document::retrieveParagraphLineBoundary",
1376 static_cast< css::uno::XWeak
* >( this ) );
1377 ::sal_Int32 nLineStart
= 0;
1378 ::sal_Int32 nLineEnd
= 0;
1379 ::sal_uInt16 nLineCount
= m_rEngine
.GetLineCount( nNumber
);
1380 for ( ::sal_uInt16 nLine
= 0; nLine
< nLineCount
; ++nLine
)
1382 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1383 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1384 nLineStart
= nLineEnd
;
1385 nLineEnd
+= nLineLength
;
1386 if ( nIndex
>= nLineStart
&& ( ( nLine
== nLineCount
- 1 ) ? nIndex
<= nLineEnd
: nIndex
< nLineEnd
) )
1388 aBoundary
.startPos
= nLineStart
;
1389 aBoundary
.endPos
= nLineEnd
;
1401 Document::retrieveParagraphBoundaryOfLine( Paragraph
const * pParagraph
,
1402 ::sal_Int32 nLineNo
)
1404 css::i18n::Boundary aBoundary
;
1405 aBoundary
.startPos
= 0;
1406 aBoundary
.endPos
= 0;
1408 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard( getExternalLock() );
1410 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1411 ::sal_uLong nNumber
= static_cast< ::sal_uLong
>( pParagraph
->getNumber() );
1412 if ( nLineNo
>= m_rEngine
.GetLineCount( nNumber
) )
1413 throw css::lang::IndexOutOfBoundsException(
1414 "textwindowaccessibility.cxx:"
1415 " Document::retrieveParagraphBoundaryOfLine",
1416 static_cast< css::uno::XWeak
* >( this ) );
1417 ::sal_Int32 nLineStart
= 0;
1418 ::sal_Int32 nLineEnd
= 0;
1419 for ( ::sal_uInt16 nLine
= 0; nLine
<= nLineNo
; ++nLine
)
1421 ::sal_Int32 nLineLength
= static_cast< ::sal_Int32
>(
1422 m_rEngine
.GetLineLen( nNumber
, nLine
) );
1423 nLineStart
= nLineEnd
;
1424 nLineEnd
+= nLineLength
;
1427 aBoundary
.startPos
= nLineStart
;
1428 aBoundary
.endPos
= nLineEnd
;
1434 sal_Int32
Document::retrieveParagraphLineWithCursor( Paragraph
const * pParagraph
)
1436 ::osl::Guard
< ::comphelper::IMutex
> aExternalGuard(getExternalLock());
1437 ::osl::MutexGuard
aInternalGuard(GetMutex());
1438 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
1439 Paragraphs::size_type nNumber
= pParagraph
->getNumber();
1440 TextPaM
aEndPaM( rSelection
.GetEnd() );
1442 return aEndPaM
.GetPara() == nNumber
1443 ? m_rView
.GetLineNumberOfCursorInSelection() : -1;
1447 css::uno::Reference
< css::accessibility::XAccessibleRelationSet
>
1448 Document::retrieveParagraphRelationSet( Paragraph
const * pParagraph
)
1450 ::osl::MutexGuard
aInternalGuard( GetMutex() );
1452 ::utl::AccessibleRelationSetHelper
* pRelationSetHelper
= new ::utl::AccessibleRelationSetHelper();
1453 css::uno::Reference
< css::accessibility::XAccessibleRelationSet
> xSet
= pRelationSetHelper
;
1455 Paragraphs::iterator
aPara( m_xParagraphs
->begin() + pParagraph
->getNumber() );
1457 if ( aPara
> m_aVisibleBegin
&& aPara
< m_aVisibleEnd
)
1459 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > aSequence(1);
1460 aSequence
[0] = getAccessibleChild( aPara
- 1 );
1461 css::accessibility::AccessibleRelation
aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM
, aSequence
);
1462 pRelationSetHelper
->AddRelation( aRelation
);
1465 if ( aPara
>= m_aVisibleBegin
&& aPara
< m_aVisibleEnd
-1 )
1467 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > aSequence(1);
1468 aSequence
[0] = getAccessibleChild( aPara
+ 1 );
1469 css::accessibility::AccessibleRelation
aRelation( css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO
, aSequence
);
1470 pRelationSetHelper
->AddRelation( aRelation
);
1477 ::sal_Int32 SAL_CALL
Document::getAccessibleChildCount()
1478 throw (css::uno::RuntimeException
, std::exception
)
1480 ::comphelper::OExternalLockGuard
aGuard(this);
1482 return m_aVisibleEnd
- m_aVisibleBegin
;
1486 css::uno::Reference
< css::accessibility::XAccessible
> SAL_CALL
1487 Document::getAccessibleChild(::sal_Int32 i
)
1488 throw (css::lang::IndexOutOfBoundsException
,
1489 css::uno::RuntimeException
, std::exception
)
1491 ::comphelper::OExternalLockGuard
aGuard(this);
1493 if (i
< 0 || i
>= m_aVisibleEnd
- m_aVisibleBegin
)
1494 throw css::lang::IndexOutOfBoundsException(
1495 "textwindowaccessibility.cxx:"
1496 " Document::getAccessibleChild",
1497 static_cast< css::uno::XWeak
* >(this));
1498 return getAccessibleChild(m_aVisibleBegin
1499 + static_cast< Paragraphs::size_type
>(i
));
1503 ::sal_Int16 SAL_CALL
Document::getAccessibleRole()
1504 throw (css::uno::RuntimeException
, std::exception
)
1506 return css::accessibility::AccessibleRole::TEXT_FRAME
;
1510 css::uno::Reference
< css::accessibility::XAccessible
> SAL_CALL
1511 Document::getAccessibleAtPoint(css::awt::Point
const & rPoint
)
1512 throw (css::uno::RuntimeException
, std::exception
)
1514 ::comphelper::OExternalLockGuard
aGuard(this);
1517 && rPoint
.X
< m_rView
.GetWindow()->GetOutputSizePixel().Width()
1518 && rPoint
.Y
>= 0 && rPoint
.Y
< m_nViewHeight
)
1520 ::sal_Int32 nOffset
= m_nViewOffset
+ rPoint
.Y
; // XXX numeric overflow
1521 ::sal_Int32 nPos
= m_nViewOffset
- m_nVisibleBeginOffset
;
1522 for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1525 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1527 return getAccessibleChild(aIt
);
1532 void Document::FillAccessibleStateSet( utl::AccessibleStateSetHelper
& rStateSet
)
1534 VCLXAccessibleComponent::FillAccessibleStateSet( rStateSet
);
1535 if (!m_rView
.IsReadOnly())
1536 rStateSet
.AddState( css::accessibility::AccessibleStateType::EDITABLE
);
1539 void Document::FillAccessibleRelationSet( utl::AccessibleRelationSetHelper
& rRelationSet
)
1541 if( getAccessibleParent()->getAccessibleContext()->getAccessibleRole() == css::accessibility::AccessibleRole::SCROLL_PANE
)
1543 css::uno::Sequence
< css::uno::Reference
< css::uno::XInterface
> > aSequence(1);
1544 aSequence
[0] = getAccessibleParent();
1545 rRelationSet
.AddRelation( css::accessibility::AccessibleRelation( css::accessibility::AccessibleRelationType::MEMBER_OF
, aSequence
) );
1549 VCLXAccessibleComponent::FillAccessibleRelationSet(rRelationSet
);
1553 void SAL_CALL
Document::disposing()
1555 m_aEngineListener
.endListening();
1556 m_aViewListener
.endListening();
1557 if (m_xParagraphs
.get() != 0)
1558 disposeParagraphs();
1559 VCLXAccessibleComponent::disposing();
1563 void Document::Notify(::SfxBroadcaster
&, ::SfxHint
const & rHint
)
1565 const TextHint
* pTextHint
= dynamic_cast<const TextHint
*>(&rHint
);
1568 ::TextHint
const & rTextHint
= *pTextHint
;
1569 switch (rTextHint
.GetId())
1571 case TEXT_HINT_PARAINSERTED
:
1572 case TEXT_HINT_PARAREMOVED
:
1573 // TEXT_HINT_PARAINSERTED and TEXT_HINT_PARAREMOVED are sent at
1574 // "unsafe" times (when the text engine has not yet re-formatted its
1575 // content), so that for example calling ::TextEngine::GetTextHeight
1576 // from within the code that handles TEXT_HINT_PARAINSERTED causes
1577 // trouble within the text engine. Therefore, these hints are just
1578 // buffered until a following ::TextEngine::FormatDoc causes a
1579 // TEXT_HINT_TEXTFORMATTED to come in:
1580 case TEXT_HINT_FORMATPARA
:
1581 // ::TextEngine::FormatDoc sends a sequence of
1582 // TEXT_HINT_FORMATPARAs, followed by an optional
1583 // TEXT_HINT_TEXTHEIGHTCHANGED, followed in all cases by one
1584 // TEXT_HINT_TEXTFORMATTED. Only the TEXT_HINT_FORMATPARAs contain
1585 // the numbers of the affected paragraphs, but they are sent
1586 // before the changes are applied. Therefore, TEXT_HINT_FORMATPARAs
1587 // are just buffered until another hint comes in:
1589 ::osl::MutexGuard
aInternalGuard(GetMutex());
1593 m_aParagraphNotifications
.push(rTextHint
);
1596 case TEXT_HINT_TEXTFORMATTED
:
1597 case TEXT_HINT_TEXTHEIGHTCHANGED
:
1598 case TEXT_HINT_MODIFIED
:
1600 ::osl::MutexGuard
aInternalGuard(GetMutex());
1603 handleParagraphNotifications();
1606 case TEXT_HINT_VIEWSCROLLED
:
1608 ::osl::MutexGuard
aInternalGuard(GetMutex());
1611 handleParagraphNotifications();
1613 ::sal_Int32 nOffset
= static_cast< ::sal_Int32
>(
1614 m_rView
.GetStartDocPos().Y());
1615 // XXX numeric overflow
1616 if (nOffset
!= m_nViewOffset
)
1618 m_nViewOffset
= nOffset
;
1620 Paragraphs::iterator
aOldVisibleBegin(
1622 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1624 determineVisibleRange();
1626 notifyVisibleRangeChanges(aOldVisibleBegin
,
1628 m_xParagraphs
->end());
1632 case TEXT_HINT_VIEWSELECTIONCHANGED
:
1633 case TEXT_HINT_VIEWCARETCHANGED
:
1635 ::osl::MutexGuard
aInternalGuard(GetMutex());
1639 if (m_aParagraphNotifications
.empty())
1641 handleSelectionChangeNotification();
1645 // TEXT_HINT_VIEWSELECTIONCHANGED is sometimes sent at
1646 // "unsafe" times (when the text engine has not yet re-
1647 // formatted its content), so that for example calling
1648 // ::TextEngine::GetTextHeight from within the code that
1649 // handles a previous TEXT_HINT_PARAINSERTED causes
1650 // trouble within the text engine. Therefore, these
1651 // hints are just buffered (along with
1652 // TEXT_HINT_PARAINSERTED/REMOVED/FORMATPARA) until a
1653 // following ::TextEngine::FormatDoc causes a
1654 // TEXT_HINT_TEXTFORMATTED to come in:
1655 m_bSelectionChangedNotification
= true;
1663 IMPL_LINK(Document
, WindowEventHandler
, ::VclSimpleEvent
*, pEvent
)
1665 switch (pEvent
->GetId())
1667 case VCLEVENT_WINDOW_RESIZE
:
1669 ::osl::MutexGuard
aInternalGuard(GetMutex());
1673 ::sal_Int32 nHeight
= static_cast< ::sal_Int32
>(
1674 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1675 // XXX numeric overflow
1676 if (nHeight
!= m_nViewHeight
)
1678 m_nViewHeight
= nHeight
;
1680 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
1681 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
1683 determineVisibleRange();
1685 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
1686 m_xParagraphs
->end());
1690 case VCLEVENT_WINDOW_GETFOCUS
:
1692 ::osl::MutexGuard
aInternalGuard(GetMutex());
1695 //to enable the PARAGRAPH to get focus for multiline edit
1696 ::sal_Int32 count
= getAccessibleChildCount();
1697 bool bEmpty
= m_aFocused
== m_aVisibleEnd
&& count
== 1;
1698 if ((m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
) || bEmpty
)
1700 Paragraphs::iterator m_aTemp
= bEmpty
? m_aVisibleBegin
: m_aFocused
;
1701 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(m_aTemp
));
1702 if (xParagraph
.is())
1704 xParagraph
->notifyEvent(
1705 css::accessibility::AccessibleEventId::
1709 css::accessibility::AccessibleStateType::
1714 ::rtl::Reference< Paragraph > xParagraph(
1715 getParagraph(m_aFocused));
1716 if (xParagraph.is())
1717 xParagraph->notifyEvent(
1718 css::accessibility::AccessibleEventId::
1722 css::accessibility::AccessibleStateType::
1727 case VCLEVENT_WINDOW_LOSEFOCUS
:
1729 ::osl::MutexGuard
aInternalGuard(GetMutex());
1732 //to enable the PARAGRAPH to get focus for multiline edit
1733 ::sal_Int32 count
= getAccessibleChildCount();
1734 bool bEmpty
= m_aFocused
== m_aVisibleEnd
&& count
== 1;
1735 if ((m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
) || bEmpty
)
1737 Paragraphs::iterator m_aTemp
= bEmpty
? m_aVisibleBegin
: m_aFocused
;
1738 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(m_aTemp
));
1739 if (xParagraph
.is())
1740 xParagraph
->notifyEvent(
1741 css::accessibility::AccessibleEventId::
1744 css::accessibility::AccessibleStateType::
1750 if (m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
1752 ::rtl::Reference< Paragraph > xParagraph(
1753 getParagraph(m_aFocused));
1754 if (xParagraph.is())
1755 xParagraph->notifyEvent(
1756 css::accessibility::AccessibleEventId::
1759 css::accessibility::AccessibleStateType::
1770 void Document::init()
1772 if (m_xParagraphs
.get() == 0)
1774 ::sal_uLong nCount
= m_rEngine
.GetParagraphCount();
1775 m_xParagraphs
.reset(new Paragraphs
);
1776 m_xParagraphs
->reserve(static_cast< Paragraphs::size_type
>(nCount
));
1777 // numeric overflow is harmless here
1778 for (::sal_uLong i
= 0; i
< nCount
; ++i
)
1779 m_xParagraphs
->push_back(ParagraphInfo(static_cast< ::sal_Int32
>(
1780 m_rEngine
.GetTextHeight(i
))));
1781 // XXX numeric overflow
1782 m_nViewOffset
= static_cast< ::sal_Int32
>(
1783 m_rView
.GetStartDocPos().Y()); // XXX numeric overflow
1784 m_nViewHeight
= static_cast< ::sal_Int32
>(
1785 m_rView
.GetWindow()->GetOutputSizePixel().Height());
1786 // XXX numeric overflow
1787 determineVisibleRange();
1788 m_nSelectionFirstPara
= -1;
1789 m_nSelectionFirstPos
= -1;
1790 m_nSelectionLastPara
= -1;
1791 m_nSelectionLastPos
= -1;
1792 m_aFocused
= m_xParagraphs
->end();
1793 m_bSelectionChangedNotification
= false;
1794 m_aEngineListener
.startListening(m_rEngine
);
1795 m_aViewListener
.startListening(*m_rView
.GetWindow());
1799 ::rtl::Reference
< Paragraph
>
1800 Document::getParagraph(Paragraphs::iterator
const & rIt
)
1802 return static_cast< Paragraph
* >(
1803 css::uno::Reference
< css::accessibility::XAccessible
>(
1804 rIt
->getParagraph()).get());
1807 css::uno::Reference
< css::accessibility::XAccessible
>
1808 Document::getAccessibleChild(Paragraphs::iterator
const & rIt
)
1810 css::uno::Reference
< css::accessibility::XAccessible
> xParagraph(
1811 rIt
->getParagraph());
1812 if (!xParagraph
.is())
1814 xParagraph
= new Paragraph(this, rIt
- m_xParagraphs
->begin());
1815 rIt
->setParagraph(xParagraph
);
1820 void Document::determineVisibleRange()
1822 Paragraphs::iterator
const aEnd
= m_xParagraphs
->end();
1824 m_aVisibleBegin
= aEnd
;
1825 m_aVisibleEnd
= aEnd
;
1826 m_nVisibleBeginOffset
= 0;
1828 ::sal_Int32 nPos
= 0;
1829 for (Paragraphs::iterator aIt
= m_xParagraphs
->begin(); m_aVisibleEnd
== aEnd
&& aIt
!= aEnd
; ++aIt
)
1831 ::sal_Int32
const nOldPos
= nPos
;
1832 nPos
+= aIt
->getHeight(); // XXX numeric overflow
1833 if (m_aVisibleBegin
== aEnd
)
1835 if (nPos
>= m_nViewOffset
)
1837 m_aVisibleBegin
= aIt
;
1838 m_nVisibleBeginOffset
= m_nViewOffset
- nOldPos
;
1843 if (nPos
>= m_nViewOffset
+ m_nViewHeight
) // XXX numeric overflow
1845 m_aVisibleEnd
= aIt
;
1851 !((m_aVisibleBegin
== m_xParagraphs
->end() && m_aVisibleEnd
== m_xParagraphs
->end() && m_nVisibleBeginOffset
== 0)
1852 || (m_aVisibleBegin
< m_aVisibleEnd
&& m_nVisibleBeginOffset
>= 0)),
1854 "invalid visible range");
1857 void Document::notifyVisibleRangeChanges(
1858 Paragraphs::iterator
const & rOldVisibleBegin
,
1859 Paragraphs::iterator
const & rOldVisibleEnd
,
1860 Paragraphs::iterator
const & rInserted
)
1862 // XXX Replace this code that determines which paragraphs have changed from
1863 // invisible to visible or vice versa with a better algorithm.
1864 for (Paragraphs::iterator
aIt(rOldVisibleBegin
); aIt
!= rOldVisibleEnd
;
1867 if (aIt
!= rInserted
1868 && (aIt
< m_aVisibleBegin
|| aIt
>= m_aVisibleEnd
))
1869 NotifyAccessibleEvent(
1870 css::accessibility::AccessibleEventId::
1872 css::uno::makeAny(getAccessibleChild(aIt
)),
1875 for (Paragraphs::iterator
aIt(m_aVisibleBegin
); aIt
!= m_aVisibleEnd
;
1878 if (aIt
== rInserted
1879 || aIt
< rOldVisibleBegin
|| aIt
>= rOldVisibleEnd
)
1880 NotifyAccessibleEvent(
1881 css::accessibility::AccessibleEventId::
1884 css::uno::makeAny(getAccessibleChild(aIt
)));
1889 Document::changeParagraphText(::sal_uLong nNumber
, ::sal_uInt16 nBegin
, ::sal_uInt16 nEnd
,
1890 bool bCut
, bool bPaste
,
1891 OUString
const & rText
)
1893 m_rView
.SetSelection(::TextSelection(::TextPaM(nNumber
, nBegin
),
1894 ::TextPaM(nNumber
, nEnd
)));
1897 else if (nBegin
!= nEnd
)
1898 m_rView
.DeleteSelected();
1901 else if (!rText
.isEmpty())
1902 m_rView
.InsertText(rText
);
1905 void Document::handleParagraphNotifications()
1907 while (!m_aParagraphNotifications
.empty())
1909 ::TextHint
aHint(m_aParagraphNotifications
.front());
1910 m_aParagraphNotifications
.pop();
1911 switch (aHint
.GetId())
1913 case TEXT_HINT_PARAINSERTED
:
1915 ::sal_uLong n
= aHint
.GetValue();
1916 OSL_ENSURE(n
<= m_xParagraphs
->size(),
1917 "bad TEXT_HINT_PARAINSERTED event");
1919 // Save the values of old iterators (the iterators themselves
1920 // will get invalidated), and adjust the old values so that they
1921 // reflect the insertion of the new paragraph:
1922 Paragraphs::size_type nOldVisibleBegin
1923 = m_aVisibleBegin
- m_xParagraphs
->begin();
1924 Paragraphs::size_type nOldVisibleEnd
1925 = m_aVisibleEnd
- m_xParagraphs
->begin();
1926 Paragraphs::size_type nOldFocused
1927 = m_aFocused
- m_xParagraphs
->begin();
1928 if (n
<= nOldVisibleBegin
)
1929 ++nOldVisibleBegin
; // XXX numeric overflow
1930 if (n
<= nOldVisibleEnd
)
1931 ++nOldVisibleEnd
; // XXX numeric overflow
1932 if (n
<= nOldFocused
)
1933 ++nOldFocused
; // XXX numeric overflow
1934 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionFirstPara
)
1935 ++m_nSelectionFirstPara
; // XXX numeric overflow
1936 if (sal::static_int_cast
<sal_Int32
>(n
) <= m_nSelectionLastPara
)
1937 ++m_nSelectionLastPara
; // XXX numeric overflow
1939 Paragraphs::iterator
aIns(
1940 m_xParagraphs
->insert(
1941 m_xParagraphs
->begin() + n
,
1942 ParagraphInfo(static_cast< ::sal_Int32
>(
1943 m_rEngine
.GetTextHeight(n
)))));
1944 // XXX numeric overflow (2x)
1946 determineVisibleRange();
1947 m_aFocused
= m_xParagraphs
->begin() + nOldFocused
;
1949 for (Paragraphs::iterator
aIt(aIns
);;)
1952 if (aIt
== m_xParagraphs
->end())
1954 ::rtl::Reference
< Paragraph
> xParagraph(
1956 if (xParagraph
.is())
1957 xParagraph
->numberChanged(true);
1960 notifyVisibleRangeChanges(
1961 m_xParagraphs
->begin() + nOldVisibleBegin
,
1962 m_xParagraphs
->begin() + nOldVisibleEnd
, aIns
);
1965 case TEXT_HINT_PARAREMOVED
:
1967 ::sal_uLong n
= aHint
.GetValue();
1968 if (n
== TEXT_PARA_ALL
)
1970 for (Paragraphs::iterator
aIt(m_aVisibleBegin
);
1971 aIt
!= m_aVisibleEnd
; ++aIt
)
1973 NotifyAccessibleEvent(
1974 css::accessibility::AccessibleEventId::
1976 css::uno::makeAny(getAccessibleChild(aIt
)),
1979 disposeParagraphs();
1980 m_xParagraphs
->clear();
1981 determineVisibleRange();
1982 m_nSelectionFirstPara
= -1;
1983 m_nSelectionFirstPos
= -1;
1984 m_nSelectionLastPara
= -1;
1985 m_nSelectionLastPos
= -1;
1986 m_aFocused
= m_xParagraphs
->end();
1990 OSL_ENSURE(n
< m_xParagraphs
->size(),
1991 "Bad TEXT_HINT_PARAREMOVED event");
1993 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
1994 // numeric overflow cannot occur
1996 // Save the values of old iterators (the iterators
1997 // themselves will get invalidated), and adjust the old
1998 // values so that they reflect the removal of the paragraph:
1999 Paragraphs::size_type nOldVisibleBegin
2000 = m_aVisibleBegin
- m_xParagraphs
->begin();
2001 Paragraphs::size_type nOldVisibleEnd
2002 = m_aVisibleEnd
- m_xParagraphs
->begin();
2004 = nOldVisibleBegin
<= n
&& n
< nOldVisibleEnd
;
2005 Paragraphs::size_type nOldFocused
2006 = m_aFocused
- m_xParagraphs
->begin();
2007 bool bWasFocused
= aIt
== m_aFocused
;
2008 if (n
< nOldVisibleBegin
)
2010 if (n
< nOldVisibleEnd
)
2012 if (n
< nOldFocused
)
2014 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionFirstPara
)
2015 --m_nSelectionFirstPara
;
2016 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionFirstPara
)
2018 if (m_nSelectionFirstPara
== m_nSelectionLastPara
)
2020 m_nSelectionFirstPara
= -1;
2021 m_nSelectionFirstPos
= -1;
2022 m_nSelectionLastPara
= -1;
2023 m_nSelectionLastPos
= -1;
2027 ++m_nSelectionFirstPara
;
2028 m_nSelectionFirstPos
= 0;
2031 if (sal::static_int_cast
<sal_Int32
>(n
) < m_nSelectionLastPara
)
2032 --m_nSelectionLastPara
;
2033 else if (sal::static_int_cast
<sal_Int32
>(n
) == m_nSelectionLastPara
)
2035 OSL_ENSURE(m_nSelectionFirstPara
< m_nSelectionLastPara
,
2037 --m_nSelectionLastPara
;
2038 m_nSelectionLastPos
= 0x7FFFFFFF;
2041 css::uno::Reference
< css::accessibility::XAccessible
>
2044 xStrong
= getAccessibleChild(aIt
);
2045 css::uno::WeakReference
<
2046 css::accessibility::XAccessible
> xWeak(
2047 aIt
->getParagraph());
2048 aIt
= m_xParagraphs
->erase(aIt
);
2050 determineVisibleRange();
2051 m_aFocused
= bWasFocused
? m_xParagraphs
->end()
2052 : m_xParagraphs
->begin() + nOldFocused
;
2054 for (; aIt
!= m_xParagraphs
->end(); ++aIt
)
2056 ::rtl::Reference
< Paragraph
> xParagraph(
2058 if (xParagraph
.is())
2059 xParagraph
->numberChanged(false);
2063 NotifyAccessibleEvent(
2064 css::accessibility::AccessibleEventId::
2066 css::uno::makeAny(xStrong
),
2069 css::uno::Reference
< css::lang::XComponent
> xComponent(
2070 xWeak
.get(), css::uno::UNO_QUERY
);
2071 if (xComponent
.is())
2072 xComponent
->dispose();
2074 notifyVisibleRangeChanges(
2075 m_xParagraphs
->begin() + nOldVisibleBegin
,
2076 m_xParagraphs
->begin() + nOldVisibleEnd
,
2077 m_xParagraphs
->end());
2081 case TEXT_HINT_FORMATPARA
:
2083 ::sal_uLong n
= aHint
.GetValue();
2084 OSL_ENSURE(n
< m_xParagraphs
->size(),
2085 "Bad TEXT_HINT_FORMATPARA event");
2087 (*m_xParagraphs
)[static_cast< Paragraphs::size_type
>(n
)].
2088 changeHeight(static_cast< ::sal_Int32
>(
2089 m_rEngine
.GetTextHeight(n
)));
2090 // XXX numeric overflow
2091 Paragraphs::iterator
aOldVisibleBegin(m_aVisibleBegin
);
2092 Paragraphs::iterator
aOldVisibleEnd(m_aVisibleEnd
);
2093 determineVisibleRange();
2094 notifyVisibleRangeChanges(aOldVisibleBegin
, aOldVisibleEnd
,
2095 m_xParagraphs
->end());
2097 if (n
< m_xParagraphs
->size())
2099 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + n
);
2100 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(aIt
));
2101 if (xParagraph
.is())
2102 xParagraph
->textChanged();
2107 OSL_FAIL( "bad buffered hint");
2111 if (m_bSelectionChangedNotification
)
2113 m_bSelectionChangedNotification
= false;
2114 handleSelectionChangeNotification();
2118 ::sal_Int32
Document::getSelectionType(::sal_Int32 nNewFirstPara
, ::sal_Int32 nNewFirstPos
, ::sal_Int32 nNewLastPara
, ::sal_Int32 nNewLastPos
)
2120 if (m_nSelectionFirstPara
== -1)
2122 ::sal_Int32 Osp
= m_nSelectionFirstPara
, Osl
= m_nSelectionFirstPos
, Oep
= m_nSelectionLastPara
, Oel
= m_nSelectionLastPos
;
2123 ::sal_Int32 Nsp
= nNewFirstPara
, Nsl
= nNewFirstPos
, Nep
= nNewLastPara
, Nel
= nNewLastPos
;
2124 TextPaM
Ns(Nsp
, sal_uInt16(Nsl
));
2125 TextPaM
Ne(Nep
, sal_uInt16(Nel
));
2126 TextPaM
Os(Osp
, sal_uInt16(Osl
));
2127 TextPaM
Oe(Oep
, sal_uInt16(Oel
));
2129 if (Os
== Oe
&& Ns
== Ne
)
2134 else if (Os
== Oe
&& Ns
!= Ne
)
2136 //old has no selection but new has selection
2139 else if (Os
!= Oe
&& Ns
== Ne
)
2141 //old has selection but new has no selection.
2144 else if (Os
!= Oe
&& Ns
!= Ne
&& Osp
== Nsp
&& Osl
== Nsl
)
2146 //both old and new have selections.
2149 //Send text_selection_change event on Nep
2155 //all the following examples like 1,2->1,3 means that old start select para is 1, old end select para is 2,
2156 // then press shift up, the new start select para is 1, new end select para is 3;
2157 //for example, 1, 2 -> 1, 3; 4,1 -> 4, 7; 4,1 -> 4, 2; 4,4->4,5
2160 // 1, 2 -> 1, 3; 4, 1 -> 4, 7; 4,4->4,5;
2166 else if (Oep
>= Osp
)
2168 // 1, 2 -> 1, 3; 4,4->4,5;
2180 else if (Oep
>= Osp
)
2182 // no such condition. Oep > Osp = Nsp > Nep
2188 // 3,2 -> 3,1; 4,7 -> 4,1; 4, 7 -> 4,6; 4,4 -> 4,3
2194 //no such condition, Oep<Osp=Nsp <= Nep
2204 // 3,2 -> 3,1, 4,7 -> 4,1; 4,4->4,3
2207 // 3,2 -> 3,1; 4,4->4,3
2222 void Document::sendEvent(::sal_Int32 start
, ::sal_Int32 end
, ::sal_Int16 nEventId
)
2224 size_t nAvailDistance
= std::distance(m_xParagraphs
->begin(), m_aVisibleEnd
);
2226 Paragraphs::iterator
aEnd(m_xParagraphs
->begin());
2227 size_t nEndDistance
= std::min
<size_t>(end
+ 1, nAvailDistance
);
2228 std::advance(aEnd
, nEndDistance
);
2230 Paragraphs::iterator
aIt(m_xParagraphs
->begin());
2231 size_t nStartDistance
= std::min
<size_t>(start
, nAvailDistance
);
2232 std::advance(aIt
, nStartDistance
);
2236 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(aIt
));
2237 if (xParagraph
.is())
2238 xParagraph
->notifyEvent(
2240 css::uno::Any(), css::uno::Any());
2245 void Document::handleSelectionChangeNotification()
2247 ::TextSelection
const & rSelection
= m_rView
.GetSelection();
2248 OSL_ENSURE(rSelection
.GetStart().GetPara() < m_xParagraphs
->size()
2249 && rSelection
.GetEnd().GetPara() < m_xParagraphs
->size(),
2250 "bad TEXT_HINT_VIEWSELECTIONCHANGED event");
2251 ::sal_Int32 nNewFirstPara
2252 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetPara());
2253 ::sal_Int32 nNewFirstPos
2254 = static_cast< ::sal_Int32
>(rSelection
.GetStart().GetIndex());
2255 // XXX numeric overflow
2256 ::sal_Int32 nNewLastPara
2257 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetPara());
2258 ::sal_Int32 nNewLastPos
2259 = static_cast< ::sal_Int32
>(rSelection
.GetEnd().GetIndex());
2260 // XXX numeric overflow
2263 Paragraphs::iterator
aIt(m_xParagraphs
->begin() + nNewLastPara
);
2264 if (m_aFocused
!= m_xParagraphs
->end() && m_aFocused
!= aIt
2265 && m_aFocused
>= m_aVisibleBegin
&& m_aFocused
< m_aVisibleEnd
)
2267 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(m_aFocused
));
2268 if (xParagraph
.is())
2269 xParagraph
->notifyEvent(
2270 css::accessibility::AccessibleEventId::
2273 css::accessibility::AccessibleStateType::FOCUSED
),
2277 // Gain focus and update cursor position:
2278 if (aIt
>= m_aVisibleBegin
&& aIt
< m_aVisibleEnd
2279 && (aIt
!= m_aFocused
2280 || nNewLastPara
!= m_nSelectionLastPara
2281 || nNewLastPos
!= m_nSelectionLastPos
))
2283 ::rtl::Reference
< Paragraph
> xParagraph(getParagraph(aIt
));
2284 if (xParagraph
.is())
2286 //disable the first event when user types in empty field.
2287 ::sal_Int32 count
= getAccessibleChildCount();
2288 bool bEmpty
= count
> 1;
2289 //if (aIt != m_aFocused)
2290 if (aIt
!= m_aFocused
&& bEmpty
)
2291 xParagraph
->notifyEvent(
2292 css::accessibility::AccessibleEventId::
2296 css::accessibility::AccessibleStateType::FOCUSED
));
2297 if (nNewLastPara
!= m_nSelectionLastPara
2298 || nNewLastPos
!= m_nSelectionLastPos
)
2299 xParagraph
->notifyEvent(
2300 css::accessibility::AccessibleEventId::
2302 css::uno::makeAny
< ::sal_Int32
>(
2303 nNewLastPara
== m_nSelectionLastPara
2304 ? m_nSelectionLastPos
: 0),
2305 css::uno::makeAny(nNewLastPos
));
2312 ::sal_Int32 ret
= getSelectionType(nNewFirstPara
, nNewFirstPos
, nNewLastPara
, nNewLastPos
);
2322 //only caret moved, already handled in above
2327 //old has no selection but new has selection
2328 nMin
= ::std::min(nNewFirstPara
, nNewLastPara
);
2329 nMax
= ::std::max(nNewFirstPara
, nNewLastPara
);
2330 sendEvent(nMin
, nMax
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2331 sendEvent(nMin
, nMax
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2336 //old has selection but new has no selection.
2337 nMin
= ::std::min(m_nSelectionFirstPara
, m_nSelectionLastPara
);
2338 nMax
= ::std::max(m_nSelectionFirstPara
, m_nSelectionLastPara
);
2339 sendEvent(nMin
, nMax
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2340 sendEvent(nMin
, nMax
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2345 //Send text_selection_change event on Nep
2346 sendEvent(nNewLastPara
, nNewLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2352 sendEvent(m_nSelectionLastPara
, m_nSelectionFirstPara
-1, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2353 sendEvent(nNewFirstPara
+1, nNewLastPara
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2355 sendEvent(m_nSelectionLastPara
, nNewLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2360 // 1, 2 -> 1, 4; 4,4->4,5;
2361 sendEvent(m_nSelectionLastPara
+1, nNewLastPara
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2363 sendEvent(m_nSelectionLastPara
, nNewLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2369 sendEvent(m_nSelectionLastPara
+1, nNewLastPara
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2371 sendEvent(m_nSelectionLastPara
, nNewLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2377 sendEvent(nNewLastPara
+ 1, m_nSelectionLastPara
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2379 sendEvent(nNewLastPara
, m_nSelectionLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2384 // 3,2 -> 3,1; 4,4->4,3
2385 sendEvent(nNewLastPara
, m_nSelectionLastPara
- 1, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2387 sendEvent(nNewLastPara
, m_nSelectionLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2393 sendEvent(m_nSelectionFirstPara
+ 1, m_nSelectionLastPara
, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2394 sendEvent(nNewLastPara
, nNewFirstPara
- 1, css::accessibility::AccessibleEventId::SELECTION_CHANGED
);
2396 sendEvent(nNewLastPara
, m_nSelectionLastPara
, css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED
);
2404 // Update both old and new selection. (Regardless of how the two selections
2405 // look like, there will always be two ranges to the left and right of the
2406 // overlap---the overlap and/or the range to the right of it possibly being
2407 // empty. Only for these two ranges notifications have to be sent.)
2409 TextPaM aOldTextStart( static_cast< sal_uLong >( m_nSelectionFirstPara ), static_cast< sal_uInt16 >( m_nSelectionFirstPos ) );
2410 TextPaM aOldTextEnd( static_cast< sal_uLong >( m_nSelectionLastPara ), static_cast< sal_uInt16 >( m_nSelectionLastPos ) );
2411 TextPaM aNewTextStart( static_cast< sal_uLong >( nNewFirstPara ), static_cast< sal_uInt16 >( nNewFirstPos ) );
2412 TextPaM aNewTextEnd( static_cast< sal_uLong >( nNewLastPara ), static_cast< sal_uInt16 >( nNewLastPos ) );
2414 // justify selections
2415 justifySelection( aOldTextStart, aOldTextEnd );
2416 justifySelection( aNewTextStart, aNewTextEnd );
2423 if ( m_nSelectionFirstPara == -1 )
2425 // old selection not initialized yet => notify events only for new selection (if not empty)
2426 nFirst1 = aNewTextStart.GetPara();
2427 nLast1 = aNewTextEnd.GetPara() + ( aNewTextStart != aNewTextEnd ? 1 : 0 );
2431 else if ( aOldTextStart == aOldTextEnd && aNewTextStart == aNewTextEnd )
2433 // old and new selection empty => no events
2439 else if ( aOldTextStart != aOldTextEnd && aNewTextStart == aNewTextEnd )
2441 // old selection not empty + new selection empty => notify events only for old selection
2442 nFirst1 = aOldTextStart.GetPara();
2443 nLast1 = aOldTextEnd.GetPara() + 1;
2447 else if ( aOldTextStart == aOldTextEnd && aNewTextStart != aNewTextEnd )
2449 // old selection empty + new selection not empty => notify events only for new selection
2450 nFirst1 = aNewTextStart.GetPara();
2451 nLast1 = aNewTextEnd.GetPara() + 1;
2457 // old and new selection not empty => notify events for the two ranges left and right of the overlap
2458 ::std::vector< TextPaM > aTextPaMs(4);
2459 aTextPaMs[0] = aOldTextStart;
2460 aTextPaMs[1] = aOldTextEnd;
2461 aTextPaMs[2] = aNewTextStart;
2462 aTextPaMs[3] = aNewTextEnd;
2463 ::std::sort( aTextPaMs.begin(), aTextPaMs.end() );
2465 nFirst1 = aTextPaMs[0].GetPara();
2466 nLast1 = aTextPaMs[1].GetPara() + ( aTextPaMs[0] != aTextPaMs[1] ? 1 : 0 );
2468 nFirst2 = aTextPaMs[2].GetPara();
2469 nLast2 = aTextPaMs[3].GetPara() + ( aTextPaMs[2] != aTextPaMs[3] ? 1 : 0 );
2471 // adjust overlapping ranges
2472 if ( nLast1 > nFirst2 )
2476 // notify selection changes
2477 notifySelectionChange( nFirst1, nLast1 );
2478 notifySelectionChange( nFirst2, nLast2 );
2480 m_nSelectionFirstPara
= nNewFirstPara
;
2481 m_nSelectionFirstPos
= nNewFirstPos
;
2482 m_nSelectionLastPara
= nNewLastPara
;
2483 m_nSelectionLastPos
= nNewLastPos
;
2486 void Document::disposeParagraphs()
2488 for (Paragraphs::iterator
aIt(m_xParagraphs
->begin());
2489 aIt
!= m_xParagraphs
->end(); ++aIt
)
2491 css::uno::Reference
< css::lang::XComponent
> xComponent(
2492 aIt
->getParagraph().get(), css::uno::UNO_QUERY
);
2493 if (xComponent
.is())
2494 xComponent
->dispose();
2499 css::uno::Any
Document::mapFontColor(::Color
const & rColor
)
2501 return css::uno::makeAny(
2502 static_cast< ::sal_Int32
>(COLORDATA_RGB(rColor
.GetColor())));
2503 // FIXME keep transparency?
2507 ::Color
Document::mapFontColor(css::uno::Any
const & rColor
)
2509 ::sal_Int32 nColor
= 0;
2511 return ::Color(static_cast< ::ColorData
>(nColor
));
2515 css::uno::Any
Document::mapFontWeight(::FontWeight nWeight
)
2517 // Map from ::FontWeight to css::awt::FontWeight, depends on order of
2518 // elements in ::FontWeight (vcl/vclenum.hxx):
2519 static float const aWeight
[]
2520 = { css::awt::FontWeight::DONTKNOW
, // WEIGHT_DONTKNOW
2521 css::awt::FontWeight::THIN
, // WEIGHT_THIN
2522 css::awt::FontWeight::ULTRALIGHT
, // WEIGHT_ULTRALIGHT
2523 css::awt::FontWeight::LIGHT
, // WEIGHT_LIGHT
2524 css::awt::FontWeight::SEMILIGHT
, // WEIGHT_SEMILIGHT
2525 css::awt::FontWeight::NORMAL
, // WEIGHT_NORMAL
2526 css::awt::FontWeight::NORMAL
, // WEIGHT_MEDIUM
2527 css::awt::FontWeight::SEMIBOLD
, // WEIGHT_SEMIBOLD
2528 css::awt::FontWeight::BOLD
, // WEIGHT_BOLD
2529 css::awt::FontWeight::ULTRABOLD
, // WEIGHT_ULTRABOLD
2530 css::awt::FontWeight::BLACK
}; // WEIGHT_BLACK
2531 return css::uno::makeAny(aWeight
[nWeight
]);
2535 ::FontWeight
Document::mapFontWeight(css::uno::Any
const & rWeight
)
2537 float nWeight
= css::awt::FontWeight::NORMAL
;
2538 rWeight
>>= nWeight
;
2539 return nWeight
<= css::awt::FontWeight::DONTKNOW
? WEIGHT_DONTKNOW
2540 : nWeight
<= css::awt::FontWeight::THIN
? WEIGHT_THIN
2541 : nWeight
<= css::awt::FontWeight::ULTRALIGHT
? WEIGHT_ULTRALIGHT
2542 : nWeight
<= css::awt::FontWeight::LIGHT
? WEIGHT_LIGHT
2543 : nWeight
<= css::awt::FontWeight::SEMILIGHT
? WEIGHT_SEMILIGHT
2544 : nWeight
<= css::awt::FontWeight::NORMAL
? WEIGHT_NORMAL
2545 : nWeight
<= css::awt::FontWeight::SEMIBOLD
? WEIGHT_SEMIBOLD
2546 : nWeight
<= css::awt::FontWeight::BOLD
? WEIGHT_BOLD
2547 : nWeight
<= css::awt::FontWeight::ULTRABOLD
? WEIGHT_ULTRABOLD
2553 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */