LCOV - code coverage report
Current view: top level - libreoffice/accessibility/source/extended - textwindowaccessibility.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 970 0.0 %
Date: 2012-12-27 Functions: 0 120 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      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 .
      18             :  */
      19             : 
      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>
      26             : 
      27             : #include <algorithm>
      28             : #include <vector>
      29             : #include <boost/unordered_map.hpp>
      30             : 
      31             : namespace accessibility
      32             : {
      33             : 
      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           0 : class Paragraph: private ::osl::Mutex, public ParagraphImpl
      38             : {
      39             : public:
      40           0 :     inline Paragraph(::rtl::Reference< Document > const & rDocument,
      41             :                      Paragraphs::size_type nNumber):
      42           0 :         ParagraphImpl(rDocument, nNumber, *this) {}
      43             : };
      44             : 
      45           0 : void SfxListenerGuard::startListening(::SfxBroadcaster & rNotifier)
      46             : {
      47             :     OSL_ENSURE(m_pNotifier == 0, "called more than once");
      48           0 :     m_pNotifier = &rNotifier;
      49           0 :     m_rListener.StartListening(*m_pNotifier, true);
      50           0 : }
      51             : 
      52           0 : void SfxListenerGuard::endListening()
      53             : {
      54           0 :     if (m_pNotifier != 0)
      55             :     {
      56           0 :         m_rListener.EndListening(*m_pNotifier);
      57           0 :         m_pNotifier = 0;
      58             :     }
      59           0 : }
      60             : 
      61           0 : void WindowListenerGuard::startListening(::Window & rNotifier)
      62             : {
      63             :     OSL_ENSURE(m_pNotifier == 0, "called more than once");
      64           0 :     m_pNotifier = &rNotifier;
      65           0 :     m_pNotifier->AddEventListener(m_aListener);
      66           0 : }
      67             : 
      68           0 : void WindowListenerGuard::endListening()
      69             : {
      70           0 :     if (m_pNotifier != 0)
      71             :     {
      72           0 :         m_pNotifier->RemoveEventListener(m_aListener);
      73           0 :         m_pNotifier = 0;
      74             :     }
      75           0 : }
      76             : 
      77           0 : ParagraphImpl::ParagraphImpl(::rtl::Reference< Document > const & rDocument,
      78             :                              Paragraphs::size_type nNumber,
      79             :                              ::osl::Mutex & rMutex):
      80             :     ParagraphBase(rMutex),
      81             :     m_xDocument(rDocument),
      82             :     m_nNumber(nNumber),
      83           0 :     m_nClientId(0)
      84             : {
      85           0 :     m_aParagraphText = m_xDocument->retrieveParagraphText(this);
      86           0 : }
      87             : 
      88             : void
      89           0 : ParagraphImpl::numberChanged(bool bIncremented)
      90             : {
      91           0 :     if (bIncremented)
      92           0 :         ++m_nNumber;
      93             :     else
      94           0 :         --m_nNumber;
      95           0 : }
      96             : 
      97           0 : void ParagraphImpl::textChanged()
      98             : {
      99           0 :     OUString aParagraphText = implGetText();
     100           0 :     ::css::uno::Any aOldValue, aNewValue;
     101           0 :     if ( implInitTextChangedEvent( m_aParagraphText, aParagraphText, aOldValue, aNewValue ) )
     102             :     {
     103           0 :         m_aParagraphText = aParagraphText;
     104             :         notifyEvent(::css::accessibility::AccessibleEventId::
     105             :                     TEXT_CHANGED,
     106           0 :                     aOldValue, aNewValue);
     107           0 :     }
     108           0 : }
     109             : 
     110           0 : void ParagraphImpl::notifyEvent(::sal_Int16 nEventId,
     111             :                                 ::css::uno::Any const & rOldValue,
     112             :                                 ::css::uno::Any const & rNewValue)
     113             : {
     114           0 :     if (m_nClientId)
     115             :         comphelper::AccessibleEventNotifier::addEvent( m_nClientId, ::css::accessibility::AccessibleEventObject(
     116             :                              static_cast< ::cppu::OWeakObject * >(this),
     117           0 :                              nEventId, rNewValue, rOldValue) );
     118           0 : }
     119             : 
     120             : // virtual
     121             : ::css::uno::Reference< ::css::accessibility::XAccessibleContext > SAL_CALL
     122           0 : ParagraphImpl::getAccessibleContext() throw (::css::uno::RuntimeException)
     123             : {
     124           0 :     checkDisposed();
     125           0 :     return this;
     126             : }
     127             : 
     128             : // virtual
     129           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getAccessibleChildCount()
     130             :     throw (::css::uno::RuntimeException)
     131             : {
     132           0 :     checkDisposed();
     133           0 :     return 0;
     134             : }
     135             : 
     136             : // virtual
     137             : ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
     138           0 : ParagraphImpl::getAccessibleChild(::sal_Int32)
     139             :     throw (::css::lang::IndexOutOfBoundsException,
     140             :            ::css::uno::RuntimeException)
     141             : {
     142           0 :     checkDisposed();
     143             :     throw ::css::lang::IndexOutOfBoundsException(
     144             :         "textwindowaccessibility.cxx:"
     145             :         " ParagraphImpl::getAccessibleChild",
     146           0 :         static_cast< ::css::uno::XWeak * >(this));
     147             : }
     148             : 
     149             : // virtual
     150             : ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
     151           0 : ParagraphImpl::getAccessibleParent()
     152             :     throw (::css::uno::RuntimeException)
     153             : {
     154           0 :     checkDisposed();
     155           0 :     return m_xDocument->getAccessible();
     156             : }
     157             : 
     158             : // virtual
     159           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getAccessibleIndexInParent()
     160             :     throw (::css::uno::RuntimeException)
     161             : {
     162           0 :     checkDisposed();
     163           0 :     return m_xDocument->retrieveParagraphIndex(this);
     164             : }
     165             : 
     166             : // virtual
     167           0 : ::sal_Int16 SAL_CALL ParagraphImpl::getAccessibleRole()
     168             :     throw (::css::uno::RuntimeException)
     169             : {
     170           0 :     checkDisposed();
     171           0 :     return ::css::accessibility::AccessibleRole::PARAGRAPH;
     172             : }
     173             : 
     174             : // virtual
     175           0 : OUString SAL_CALL ParagraphImpl::getAccessibleDescription()
     176             :     throw (::css::uno::RuntimeException)
     177             : {
     178           0 :     checkDisposed();
     179           0 :     return OUString();
     180             : }
     181             : 
     182             : // virtual
     183           0 : OUString SAL_CALL ParagraphImpl::getAccessibleName()
     184             :     throw (::css::uno::RuntimeException)
     185             : {
     186           0 :     checkDisposed();
     187           0 :     return OUString();
     188             : }
     189             : 
     190             : // virtual
     191             : ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet >
     192           0 : SAL_CALL ParagraphImpl::getAccessibleRelationSet()
     193             :     throw (::css::uno::RuntimeException)
     194             : {
     195           0 :     checkDisposed();
     196           0 :     return m_xDocument->retrieveParagraphRelationSet( this );
     197             : }
     198             : 
     199             : // virtual
     200             : ::css::uno::Reference< ::css::accessibility::XAccessibleStateSet >
     201           0 : SAL_CALL ParagraphImpl::getAccessibleStateSet()
     202             :     throw (::css::uno::RuntimeException)
     203             : {
     204           0 :     checkDisposed();
     205             : 
     206             :     // FIXME  Notification of changes (STATE_CHANGED) missing when
     207             :     // m_rView.IsReadOnly() changes:
     208             :     return new ::utl::AccessibleStateSetHelper(
     209           0 :         m_xDocument->retrieveParagraphState(this));
     210             : }
     211             : 
     212             : // virtual
     213           0 : ::css::lang::Locale SAL_CALL ParagraphImpl::getLocale()
     214             :     throw (::css::accessibility::IllegalAccessibleComponentStateException,
     215             :            ::css::uno::RuntimeException)
     216             : {
     217           0 :     checkDisposed();
     218           0 :     return m_xDocument->retrieveLocale();
     219             : }
     220             : 
     221             : // virtual
     222           0 : ::sal_Bool SAL_CALL ParagraphImpl::containsPoint(::css::awt::Point const & rPoint)
     223             :     throw (::css::uno::RuntimeException)
     224             : {
     225           0 :     checkDisposed();
     226             :     ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
     227           0 :                                                                      false));
     228             :     return rPoint.X >= 0 && rPoint.X < aRect.Width
     229           0 :         && rPoint.Y >= 0 && rPoint.Y < aRect.Height;
     230             : }
     231             : 
     232             : // virtual
     233             : ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
     234           0 : ParagraphImpl::getAccessibleAtPoint(::css::awt::Point const &)
     235             :     throw (::css::uno::RuntimeException)
     236             : {
     237           0 :     checkDisposed();
     238           0 :     return 0;
     239             : }
     240             : 
     241             : // virtual
     242           0 : ::css::awt::Rectangle SAL_CALL ParagraphImpl::getBounds()
     243             :     throw (::css::uno::RuntimeException)
     244             : {
     245           0 :     checkDisposed();
     246           0 :     return m_xDocument->retrieveParagraphBounds(this, false);
     247             : }
     248             : 
     249             : // virtual
     250           0 : ::css::awt::Point SAL_CALL ParagraphImpl::getLocation()
     251             :     throw (::css::uno::RuntimeException)
     252             : {
     253           0 :     checkDisposed();
     254             :     ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
     255           0 :                                                                      false));
     256           0 :     return ::css::awt::Point(aRect.X, aRect.Y);
     257             : }
     258             : 
     259             : // virtual
     260           0 : ::css::awt::Point SAL_CALL ParagraphImpl::getLocationOnScreen()
     261             :     throw (::css::uno::RuntimeException)
     262             : {
     263           0 :     checkDisposed();
     264             :     ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
     265           0 :                                                                      true));
     266           0 :     return ::css::awt::Point(aRect.X, aRect.Y);
     267             : }
     268             : 
     269             : // virtual
     270           0 : ::css::awt::Size SAL_CALL ParagraphImpl::getSize()
     271             :     throw (::css::uno::RuntimeException)
     272             : {
     273           0 :     checkDisposed();
     274             :     ::css::awt::Rectangle aRect(m_xDocument->retrieveParagraphBounds(this,
     275           0 :                                                                      false));
     276           0 :     return ::css::awt::Size(aRect.Width, aRect.Height);
     277             : }
     278             : 
     279             : // virtual
     280           0 : void SAL_CALL ParagraphImpl::grabFocus() throw (::css::uno::RuntimeException)
     281             : {
     282           0 :     checkDisposed();
     283           0 :     Window* pWindow = m_xDocument->GetWindow();
     284           0 :     if ( pWindow )
     285             :     {
     286           0 :         pWindow->GrabFocus();
     287             :     }
     288             :     try
     289             :     {
     290           0 :         m_xDocument->changeParagraphSelection(this, 0, 0);
     291             :     }
     292           0 :     catch (const ::css::lang::IndexOutOfBoundsException & rEx)
     293             :     {
     294             :         OSL_TRACE(
     295             :             "textwindowaccessibility.cxx: ParagraphImpl::grabFocus:"
     296             :             " caught unexpected %s\n",
     297             :             OUStringToOString(rEx.Message, RTL_TEXTENCODING_UTF8).
     298             :             getStr());
     299             :     }
     300           0 : }
     301             : 
     302             : // virtual
     303           0 : ::css::uno::Any SAL_CALL ParagraphImpl::getAccessibleKeyBinding()
     304             :     throw (::css::uno::RuntimeException)
     305             : {
     306           0 :     checkDisposed();
     307           0 :     return ::css::uno::Any();
     308             : }
     309             : 
     310             : // virtual
     311           0 : ::css::util::Color SAL_CALL ParagraphImpl::getForeground()
     312             :     throw (::css::uno::RuntimeException)
     313             : {
     314           0 :     return 0; // TODO
     315             : }
     316             : 
     317             : // virtual
     318           0 : ::css::util::Color SAL_CALL ParagraphImpl::getBackground()
     319             :     throw (::css::uno::RuntimeException)
     320             : {
     321           0 :     return 0; // TODO
     322             : }
     323             : 
     324             : // virtual
     325           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getCaretPosition()
     326             :     throw (::css::uno::RuntimeException)
     327             : {
     328           0 :     checkDisposed();
     329           0 :     return m_xDocument->retrieveParagraphCaretPosition(this);
     330             : }
     331             : 
     332             : // virtual
     333           0 : ::sal_Bool SAL_CALL ParagraphImpl::setCaretPosition(::sal_Int32 nIndex)
     334             :     throw (::css::lang::IndexOutOfBoundsException,
     335             :            ::css::uno::RuntimeException)
     336             : {
     337           0 :     checkDisposed();
     338           0 :     m_xDocument->changeParagraphSelection(this, nIndex, nIndex);
     339           0 :     return true;
     340             : }
     341             : 
     342             : // virtual
     343           0 : ::sal_Unicode SAL_CALL ParagraphImpl::getCharacter(::sal_Int32 nIndex)
     344             :     throw (::css::lang::IndexOutOfBoundsException,
     345             :            ::css::uno::RuntimeException)
     346             : {
     347           0 :     checkDisposed();
     348           0 :     return OCommonAccessibleText::getCharacter(nIndex);
     349             : }
     350             : 
     351             : // virtual
     352             : ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
     353           0 : ParagraphImpl::getCharacterAttributes(::sal_Int32 nIndex, const ::com::sun::star::uno::Sequence< OUString >& aRequestedAttributes)
     354             :     throw (::css::lang::IndexOutOfBoundsException,
     355             :            ::css::uno::RuntimeException)
     356             : {
     357           0 :     checkDisposed();
     358           0 :     return m_xDocument->retrieveCharacterAttributes( this, nIndex, aRequestedAttributes );
     359             : }
     360             : 
     361             : // virtual
     362             : ::css::awt::Rectangle SAL_CALL
     363           0 : ParagraphImpl::getCharacterBounds(::sal_Int32 nIndex)
     364             :     throw (::css::lang::IndexOutOfBoundsException,
     365             :            ::css::uno::RuntimeException)
     366             : {
     367           0 :     checkDisposed();
     368           0 :     ::css::awt::Rectangle aBounds(m_xDocument->retrieveCharacterBounds(this, nIndex));
     369           0 :     ::css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
     370           0 :     aBounds.X -= aParaBounds.X;
     371           0 :     aBounds.Y -= aParaBounds.Y;
     372           0 :     return aBounds;
     373             : }
     374             : 
     375             : // virtual
     376           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getCharacterCount()
     377             :     throw (::css::uno::RuntimeException)
     378             : {
     379           0 :     checkDisposed();
     380           0 :     return OCommonAccessibleText::getCharacterCount();
     381             : }
     382             : 
     383             : // virtual
     384             : ::sal_Int32 SAL_CALL
     385           0 : ParagraphImpl::getIndexAtPoint(::css::awt::Point const & rPoint)
     386             :     throw (::css::uno::RuntimeException)
     387             : {
     388           0 :     checkDisposed();
     389           0 :     ::css::awt::Point aPoint(rPoint);
     390           0 :     ::css::awt::Rectangle aParaBounds(m_xDocument->retrieveParagraphBounds(this, false));
     391           0 :     aPoint.X += aParaBounds.X;
     392           0 :     aPoint.Y += aParaBounds.Y;
     393           0 :     return m_xDocument->retrieveCharacterIndex(this, aPoint);
     394             : }
     395             : 
     396             : // virtual
     397           0 : OUString SAL_CALL ParagraphImpl::getSelectedText()
     398             :     throw (::css::uno::RuntimeException)
     399             : {
     400           0 :     checkDisposed();
     401             : 
     402           0 :     return OCommonAccessibleText::getSelectedText();
     403             : }
     404             : 
     405             : // virtual
     406           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getSelectionStart()
     407             :     throw (::css::uno::RuntimeException)
     408             : {
     409           0 :     checkDisposed();
     410           0 :     return OCommonAccessibleText::getSelectionStart();
     411             : }
     412             : 
     413             : // virtual
     414           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getSelectionEnd()
     415             :     throw (::css::uno::RuntimeException)
     416             : {
     417           0 :     checkDisposed();
     418           0 :     return OCommonAccessibleText::getSelectionEnd();
     419             : }
     420             : 
     421             : // virtual
     422           0 : ::sal_Bool SAL_CALL ParagraphImpl::setSelection(::sal_Int32 nStartIndex,
     423             :                                                 ::sal_Int32 nEndIndex)
     424             :     throw (::css::lang::IndexOutOfBoundsException,
     425             :            ::css::uno::RuntimeException)
     426             : {
     427           0 :     checkDisposed();
     428           0 :     m_xDocument->changeParagraphSelection(this, nStartIndex, nEndIndex);
     429           0 :     return true;
     430             : }
     431             : 
     432             : // virtual
     433           0 : OUString SAL_CALL ParagraphImpl::getText()
     434             :     throw (::css::uno::RuntimeException)
     435             : {
     436           0 :     checkDisposed();
     437           0 :     return OCommonAccessibleText::getText();
     438             : }
     439             : 
     440             : // virtual
     441           0 : OUString SAL_CALL ParagraphImpl::getTextRange(::sal_Int32 nStartIndex,
     442             :                                                      ::sal_Int32 nEndIndex)
     443             :     throw (::css::lang::IndexOutOfBoundsException,
     444             :            ::css::uno::RuntimeException)
     445             : {
     446           0 :     checkDisposed();
     447           0 :     return OCommonAccessibleText::getTextRange(nStartIndex, nEndIndex);
     448             : }
     449             : 
     450             : // virtual
     451           0 : ::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)
     452             : {
     453           0 :     checkDisposed();
     454           0 :     return OCommonAccessibleText::getTextAtIndex(nIndex, aTextType);
     455             : }
     456             : 
     457             : // virtual
     458           0 : ::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)
     459             : {
     460           0 :     checkDisposed();
     461           0 :     return OCommonAccessibleText::getTextBeforeIndex(nIndex, aTextType);
     462             : }
     463             : 
     464             : // virtual
     465           0 : ::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)
     466             : {
     467           0 :     checkDisposed();
     468           0 :     return OCommonAccessibleText::getTextBehindIndex(nIndex, aTextType);
     469             : }
     470             : 
     471             : // virtual
     472           0 : ::sal_Bool SAL_CALL ParagraphImpl::copyText(::sal_Int32 nStartIndex,
     473             :                                             ::sal_Int32 nEndIndex)
     474             :     throw (::css::lang::IndexOutOfBoundsException,
     475             :            ::css::uno::RuntimeException)
     476             : {
     477           0 :     checkDisposed();
     478           0 :     m_xDocument->copyParagraphText(this, nStartIndex, nEndIndex);
     479           0 :     return true;
     480             : }
     481             : 
     482             : // virtual
     483           0 : ::sal_Bool SAL_CALL ParagraphImpl::cutText(::sal_Int32 nStartIndex,
     484             :                                            ::sal_Int32 nEndIndex)
     485             :     throw (::css::lang::IndexOutOfBoundsException,
     486             :            ::css::uno::RuntimeException)
     487             : {
     488           0 :     checkDisposed();
     489             :     m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, true, false,
     490           0 :                                      OUString());
     491           0 :     return true;
     492             : }
     493             : 
     494             : // virtual
     495           0 : ::sal_Bool SAL_CALL ParagraphImpl::pasteText(::sal_Int32 nIndex)
     496             :     throw (::css::lang::IndexOutOfBoundsException,
     497             :            ::css::uno::RuntimeException)
     498             : {
     499           0 :     checkDisposed();
     500             :     m_xDocument->changeParagraphText(this, nIndex, nIndex, false, true,
     501           0 :                                      OUString());
     502           0 :     return true;
     503             : }
     504             : 
     505             : // virtual
     506           0 : ::sal_Bool SAL_CALL ParagraphImpl::deleteText(::sal_Int32 nStartIndex,
     507             :                                           ::sal_Int32 nEndIndex)
     508             :     throw (::css::lang::IndexOutOfBoundsException,
     509             :            ::css::uno::RuntimeException)
     510             : {
     511           0 :     checkDisposed();
     512             :     m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
     513           0 :                                      OUString());
     514           0 :     return true;
     515             : }
     516             : 
     517             : // virtual
     518           0 : ::sal_Bool SAL_CALL ParagraphImpl::insertText(OUString const & rText,
     519             :                                               ::sal_Int32 nIndex)
     520             :     throw (::css::lang::IndexOutOfBoundsException,
     521             :            ::css::uno::RuntimeException)
     522             : {
     523           0 :     checkDisposed();
     524           0 :     m_xDocument->changeParagraphText(this, nIndex, nIndex, false, false, rText);
     525           0 :     return true;
     526             : }
     527             : 
     528             : // virtual
     529             : ::sal_Bool SAL_CALL
     530           0 : ParagraphImpl::replaceText(::sal_Int32 nStartIndex, ::sal_Int32 nEndIndex,
     531             :                            OUString const & rReplacement)
     532             :     throw (::css::lang::IndexOutOfBoundsException,
     533             :            ::css::uno::RuntimeException)
     534             : {
     535           0 :     checkDisposed();
     536             :     m_xDocument->changeParagraphText(this, nStartIndex, nEndIndex, false, false,
     537           0 :                                      rReplacement);
     538           0 :     return true;
     539             : }
     540             : 
     541             : // virtual
     542           0 : ::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)
     547             : {
     548           0 :     checkDisposed();
     549             :     m_xDocument->changeParagraphAttributes(this, nStartIndex, nEndIndex,
     550           0 :                                            rAttributeSet);
     551           0 :     return true;
     552             : }
     553             : 
     554             : // virtual
     555           0 : ::sal_Bool SAL_CALL ParagraphImpl::setText(OUString const & rText)
     556             :     throw (::css::uno::RuntimeException)
     557             : {
     558           0 :     checkDisposed();
     559           0 :     m_xDocument->changeParagraphText(this, rText);
     560           0 :     return true;
     561             : }
     562             : 
     563             : // virtual
     564             : ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
     565           0 : ParagraphImpl::getDefaultAttributes(const ::css::uno::Sequence< OUString >& RequestedAttributes)
     566             :     throw (::css::uno::RuntimeException)
     567             : {
     568           0 :     checkDisposed();
     569           0 :     return m_xDocument->retrieveDefaultAttributes( this, RequestedAttributes );
     570             : }
     571             : 
     572             : // virtual
     573             : ::css::uno::Sequence< ::css::beans::PropertyValue > SAL_CALL
     574           0 : ParagraphImpl::getRunAttributes(::sal_Int32 Index, const ::css::uno::Sequence< OUString >& RequestedAttributes)
     575             :     throw (::css::lang::IndexOutOfBoundsException,
     576             :            ::css::uno::RuntimeException)
     577             : {
     578           0 :     checkDisposed();
     579           0 :     return m_xDocument->retrieveRunAttributes( this, Index, RequestedAttributes );
     580             : }
     581             : 
     582             : // virtual
     583           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getLineNumberAtIndex( ::sal_Int32 nIndex )
     584             :     throw (::css::lang::IndexOutOfBoundsException,
     585             :            ::css::uno::RuntimeException)
     586             : {
     587           0 :     checkDisposed();
     588             : 
     589           0 :     ::sal_Int32 nLineNo = -1;
     590           0 :     m_xDocument->retrieveParagraphLineBoundary( this, nIndex, &nLineNo );
     591             : 
     592           0 :     return nLineNo;
     593             : }
     594             : 
     595             : // virtual
     596           0 : ::css::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextAtLineNumber( ::sal_Int32 nLineNo )
     597             :     throw (::css::lang::IndexOutOfBoundsException,
     598             :            ::css::uno::RuntimeException)
     599             : {
     600           0 :     checkDisposed();
     601             : 
     602             :     ::css::i18n::Boundary aBoundary =
     603           0 :         m_xDocument->retrieveParagraphBoundaryOfLine( this, nLineNo );
     604             : 
     605           0 :     return ::css::accessibility::TextSegment( getTextRange(aBoundary.startPos, aBoundary.endPos),
     606           0 :         aBoundary.startPos, aBoundary.endPos);
     607             : }
     608             : 
     609             : // virtual
     610           0 : ::css::accessibility::TextSegment SAL_CALL ParagraphImpl::getTextAtLineWithCaret(  )
     611             :     throw (::css::uno::RuntimeException)
     612             : {
     613           0 :     checkDisposed();
     614             : 
     615           0 :     sal_Int32 nLineNo = getNumberOfLineWithCaret();
     616             : 
     617             :     try {
     618             :         return ( nLineNo >= 0 ) ?
     619           0 :             getTextAtLineNumber( nLineNo ) :
     620           0 :             ::css::accessibility::TextSegment();
     621           0 :     } catch (const ::css::lang::IndexOutOfBoundsException&) {
     622             :         throw ::css::uno::RuntimeException(
     623             :             "textwindowaccessibility.cxx:"
     624             :             " ParagraphImpl::getTextAtLineWithCaret",
     625           0 :             static_cast< ::css::uno::XWeak * >( this ) );
     626             :     }
     627             : }
     628             : 
     629             : // virtual
     630           0 : ::sal_Int32 SAL_CALL ParagraphImpl::getNumberOfLineWithCaret(  )
     631             :     throw (::css::uno::RuntimeException)
     632             : {
     633           0 :     checkDisposed();
     634           0 :     return m_xDocument->retrieveParagraphLineWithCursor(this);
     635             : }
     636             : 
     637             : 
     638             : // virtual
     639           0 : void SAL_CALL ParagraphImpl::addAccessibleEventListener(
     640             :     ::css::uno::Reference<
     641             :     ::css::accessibility::XAccessibleEventListener > const & rListener)
     642             :     throw (::css::uno::RuntimeException)
     643             : {
     644           0 :     if (rListener.is())
     645             :     {
     646           0 :         ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
     647           0 :         if (rBHelper.bDisposed || rBHelper.bInDispose)
     648             :         {
     649           0 :             aGuard.clear();
     650           0 :             rListener->disposing(::css::lang::EventObject(
     651           0 :                                     static_cast< ::cppu::OWeakObject * >(this)));
     652             :         }
     653             :         else
     654             :         {
     655           0 :             if (!m_nClientId)
     656           0 :                 m_nClientId = comphelper::AccessibleEventNotifier::registerClient( );
     657           0 :             comphelper::AccessibleEventNotifier::addEventListener( m_nClientId, rListener );
     658           0 :         }
     659             :     }
     660           0 : }
     661             : 
     662             : // virtual
     663           0 : void SAL_CALL ParagraphImpl::removeAccessibleEventListener(
     664             :     ::css::uno::Reference<
     665             :     ::css::accessibility::XAccessibleEventListener > const & rListener)
     666             :     throw (::css::uno::RuntimeException)
     667             : {
     668           0 :     comphelper::AccessibleEventNotifier::TClientId nId = 0;
     669             :     {
     670           0 :         ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
     671           0 :         if (rListener.is() && m_nClientId != 0
     672           0 :             && comphelper::AccessibleEventNotifier::removeEventListener( m_nClientId, rListener ) == 0)
     673             :         {
     674           0 :             nId = m_nClientId;
     675           0 :             m_nClientId = 0;
     676           0 :         }
     677             :     }
     678           0 :     if (nId != 0)
     679             :     {
     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           0 :         comphelper::AccessibleEventNotifier::revokeClient(nId);
     685             :     }
     686           0 : }
     687             : 
     688             : // virtual
     689           0 : void SAL_CALL ParagraphImpl::disposing()
     690             : {
     691           0 :     comphelper::AccessibleEventNotifier::TClientId nId = 0;
     692             :     {
     693           0 :         ::osl::ClearableMutexGuard aGuard(rBHelper.rMutex);
     694           0 :         nId = m_nClientId;
     695           0 :         m_nClientId = 0;
     696             :     }
     697           0 :     if (nId != 0)
     698           0 :         comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing(nId, *this);
     699           0 : }
     700             : 
     701             : // virtual
     702           0 : OUString ParagraphImpl::implGetText()
     703             : {
     704           0 :     return m_xDocument->retrieveParagraphText(this);
     705             : }
     706             : 
     707             : // virtual
     708           0 : ::css::lang::Locale ParagraphImpl::implGetLocale()
     709             : {
     710           0 :     return m_xDocument->retrieveLocale();
     711             : }
     712             : 
     713             : // virtual
     714           0 : void ParagraphImpl::implGetSelection(::sal_Int32 & rStartIndex,
     715             :                                      ::sal_Int32 & rEndIndex)
     716             : {
     717           0 :     m_xDocument->retrieveParagraphSelection(this, &rStartIndex, &rEndIndex);
     718           0 : }
     719             : 
     720             : // virtual
     721           0 : void ParagraphImpl::implGetParagraphBoundary( ::css::i18n::Boundary& rBoundary,
     722             :                                               ::sal_Int32 nIndex )
     723             : {
     724           0 :     OUString sText( implGetText() );
     725           0 :     ::sal_Int32 nLength = sText.getLength();
     726             : 
     727           0 :     if ( implIsValidIndex( nIndex, nLength ) )
     728             :     {
     729           0 :         rBoundary.startPos = 0;
     730           0 :         rBoundary.endPos = nLength;
     731             :     }
     732             :     else
     733             :     {
     734           0 :         rBoundary.startPos = nIndex;
     735           0 :         rBoundary.endPos = nIndex;
     736           0 :     }
     737           0 : }
     738             : 
     739             : // virtual
     740           0 : void ParagraphImpl::implGetLineBoundary( ::css::i18n::Boundary& rBoundary,
     741             :                                          ::sal_Int32 nIndex )
     742             : {
     743           0 :     OUString sText( implGetText() );
     744           0 :     ::sal_Int32 nLength = sText.getLength();
     745             : 
     746           0 :     if ( implIsValidIndex( nIndex, nLength ) || nIndex == nLength )
     747             :     {
     748             :         ::css::i18n::Boundary aBoundary =
     749           0 :             m_xDocument->retrieveParagraphLineBoundary( this, nIndex );
     750           0 :         rBoundary.startPos = aBoundary.startPos;
     751           0 :         rBoundary.endPos = aBoundary.endPos;
     752             :     }
     753             :     else
     754             :     {
     755           0 :         rBoundary.startPos = nIndex;
     756           0 :         rBoundary.endPos = nIndex;
     757           0 :     }
     758           0 : }
     759             : 
     760             : 
     761           0 : void ParagraphImpl::checkDisposed()
     762             : {
     763           0 :     ::osl::MutexGuard aGuard(rBHelper.rMutex);
     764           0 :     if (!(rBHelper.bDisposed || rBHelper.bInDispose))
     765           0 :         return;
     766             :     throw ::css::lang::DisposedException(
     767           0 :         OUString(), static_cast< ::css::uno::XWeak * >(this));
     768             : }
     769             : 
     770           0 : Document::Document(::VCLXWindow * pVclXWindow, ::TextEngine & rEngine,
     771             :                    ::TextView & rView, bool bCompoundControlChild):
     772             :     VCLXAccessibleComponent(pVclXWindow),
     773             :     m_xAccessible(pVclXWindow),
     774             :     m_rEngine(rEngine),
     775             :     m_rView(rView),
     776             :     m_aEngineListener(*this),
     777             :     m_aViewListener(LINK(this, Document, WindowEventHandler)),
     778           0 :     m_bCompoundControlChild(bCompoundControlChild)
     779           0 : {}
     780             : 
     781           0 : ::css::lang::Locale Document::retrieveLocale()
     782             : {
     783           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     784           0 :     return m_rEngine.GetLocale();
     785             : }
     786             : 
     787           0 : ::sal_Int32 Document::retrieveParagraphIndex(ParagraphImpl const * pParagraph)
     788             : {
     789           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     790             : 
     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           0 :     Paragraphs::iterator aPara(m_xParagraphs->begin()
     795           0 :                                + pParagraph->getNumber());
     796           0 :     return aPara < m_aVisibleBegin || aPara >= m_aVisibleEnd
     797           0 :         ? -1 : static_cast< ::sal_Int32 >(aPara - m_aVisibleBegin);
     798             :         // XXX  numeric overflow
     799             : }
     800             : 
     801           0 : ::sal_Int64 Document::retrieveParagraphState(ParagraphImpl const * pParagraph)
     802             : {
     803           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     804             : 
     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:
     808             :     ::sal_Int64 nState
     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           0 :              << ::css::accessibility::AccessibleStateType::MULTI_LINE);
     817           0 :     if (!m_rView.IsReadOnly())
     818             :         nState |= (static_cast< ::sal_Int64 >(1)
     819           0 :                    << ::css::accessibility::AccessibleStateType::EDITABLE);
     820           0 :     Paragraphs::iterator aPara(m_xParagraphs->begin()
     821           0 :                                + pParagraph->getNumber());
     822           0 :     if (aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd)
     823             :     {
     824             :         nState
     825             :             |= (static_cast< ::sal_Int64 >(1)
     826             :                 << ::css::accessibility::AccessibleStateType::VISIBLE)
     827             :             | (static_cast< ::sal_Int64 >(1)
     828           0 :                << ::css::accessibility::AccessibleStateType::SHOWING);
     829           0 :         if (aPara == m_aFocused)
     830             :             nState |= (static_cast< ::sal_Int64 >(1)
     831           0 :                        << ::css::accessibility::AccessibleStateType::FOCUSED);
     832             :     }
     833           0 :     return nState;
     834             : };
     835             : 
     836             : ::css::awt::Rectangle
     837           0 : Document::retrieveParagraphBounds(ParagraphImpl const * pParagraph,
     838             :                                   bool bAbsolute)
     839             : {
     840           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     841           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     842             : 
     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           0 :     Paragraphs::iterator aPara(m_xParagraphs->begin()
     849           0 :                                + pParagraph->getNumber());
     850             :     ::sal_Int32 nPos;
     851           0 :     Paragraphs::iterator aIt;
     852           0 :     if (aPara < m_aVisibleBegin)
     853             :     {
     854           0 :         nPos = 0;
     855           0 :         aIt = m_xParagraphs->begin();
     856             :     }
     857             :     else
     858             :     {
     859           0 :         nPos = m_nViewOffset - m_nVisibleBeginOffset;
     860           0 :         aIt = m_aVisibleBegin;
     861             :     }
     862           0 :     for (; aIt != aPara; ++aIt)
     863           0 :         nPos += aIt->getHeight();
     864             : 
     865           0 :     Point aOrig(0, 0);
     866           0 :     if (bAbsolute)
     867           0 :         aOrig = m_rView.GetWindow()->OutputToAbsoluteScreenPixel(aOrig);
     868             : 
     869             :     return ::css::awt::Rectangle(
     870           0 :         static_cast< ::sal_Int32 >(aOrig.X()),
     871           0 :         static_cast< ::sal_Int32 >(aOrig.Y()) + nPos - m_nViewOffset,
     872           0 :         m_rView.GetWindow()->GetOutputSizePixel().Width(), aPara->getHeight());
     873             :         // XXX  numeric overflow (3x)
     874             : }
     875             : 
     876             : OUString
     877           0 : Document::retrieveParagraphText(ParagraphImpl const * pParagraph)
     878             : {
     879           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     880           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     881           0 :     return m_rEngine.GetText(static_cast< ::sal_uLong >(pParagraph->getNumber()));
     882             :         // numeric overflow cannot happen here
     883             : }
     884             : 
     885           0 : void Document::retrieveParagraphSelection(ParagraphImpl const * pParagraph,
     886             :                                           ::sal_Int32 * pBegin,
     887             :                                           ::sal_Int32 * pEnd)
     888             : {
     889           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     890           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     891           0 :     ::TextSelection const & rSelection = m_rView.GetSelection();
     892           0 :     Paragraphs::size_type nNumber = pParagraph->getNumber();
     893           0 :     TextPaM aStartPaM( rSelection.GetStart() );
     894           0 :     TextPaM aEndPaM( rSelection.GetEnd() );
     895           0 :     TextPaM aMinPaM( ::std::min( aStartPaM, aEndPaM ) );
     896           0 :     TextPaM aMaxPaM( ::std::max( aStartPaM, aEndPaM ) );
     897             : 
     898           0 :     if ( nNumber >= aMinPaM.GetPara() && nNumber <= aMaxPaM.GetPara() )
     899             :     {
     900           0 :         *pBegin = nNumber > aMinPaM.GetPara()
     901             :             ? 0
     902           0 :             : static_cast< ::sal_Int32 >( aMinPaM.GetIndex() );
     903             :             // XXX numeric overflow
     904           0 :         *pEnd = nNumber < aMaxPaM.GetPara()
     905           0 :             ? static_cast< ::sal_Int32 >( m_rEngine.GetText(static_cast< ::sal_uLong >(nNumber)).Len() )
     906           0 :             : static_cast< ::sal_Int32 >( aMaxPaM.GetIndex() );
     907             :             // XXX  numeric overflow (3x)
     908             : 
     909           0 :         if ( aStartPaM > aEndPaM )
     910           0 :             ::std::swap( *pBegin, *pEnd );
     911             :     }
     912             :     else
     913             :     {
     914           0 :         *pBegin = 0;
     915           0 :         *pEnd = 0;
     916           0 :     }
     917           0 : }
     918             : 
     919           0 : ::sal_Int32 Document::retrieveParagraphCaretPosition(ParagraphImpl const * pParagraph)
     920             : {
     921           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     922           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     923           0 :     ::TextSelection const & rSelection = m_rView.GetSelection();
     924           0 :     Paragraphs::size_type nNumber = pParagraph->getNumber();
     925           0 :     TextPaM aEndPaM( rSelection.GetEnd() );
     926             : 
     927           0 :     return aEndPaM.GetPara() == nNumber
     928           0 :         ? static_cast< ::sal_Int32 >(aEndPaM.GetIndex()) : -1;
     929             : }
     930             : 
     931             : ::css::awt::Rectangle
     932           0 : Document::retrieveCharacterBounds(ParagraphImpl const * pParagraph,
     933             :                                   ::sal_Int32 nIndex)
     934             : {
     935           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     936           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     937           0 :     ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
     938           0 :     sal_Int32 nLength = m_rEngine.GetText(nNumber).Len();
     939             :         // XXX  numeric overflow
     940           0 :     if (nIndex < 0 || nIndex > nLength)
     941             :         throw ::css::lang::IndexOutOfBoundsException(
     942             :             "textwindowaccessibility.cxx:"
     943             :             " Document::retrieveCharacterAttributes",
     944           0 :             static_cast< ::css::uno::XWeak * >(this));
     945           0 :     ::css::awt::Rectangle aBounds( 0, 0, 0, 0 );
     946           0 :     if ( nIndex == nLength )
     947             :     {
     948             :         aBounds = AWTRectangle(
     949             :             m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
     950           0 :                                                 static_cast< ::sal_uInt16 >(nIndex))));
     951             :     }
     952             :     else
     953             :     {
     954             :         ::Rectangle aLeft(
     955             :             m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
     956           0 :                                                 static_cast< ::sal_uInt16 >(nIndex))));
     957             :             // XXX  numeric overflow
     958             :         ::Rectangle aRight(
     959             :             m_rEngine.PaMtoEditCursor(::TextPaM(nNumber,
     960             :                                                 static_cast< ::sal_uInt16 >(nIndex)
     961           0 :                                                 + 1)));
     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           0 :         ::sal_Int32 nWidth = (aLeft.Top() == aRight.Top()
     967           0 :                             && aLeft.Bottom() == aRight.Bottom())
     968           0 :             ? static_cast< ::sal_Int32 >(aRight.Left() - aLeft.Left())
     969           0 :             : static_cast< ::sal_Int32 >(m_rEngine.GetMaxTextWidth()
     970           0 :                                         - aLeft.Left());
     971             :             // XXX  numeric overflow (4x)
     972           0 :         aBounds = ::css::awt::Rectangle(static_cast< ::sal_Int32 >(aLeft.Left()),
     973           0 :                                         static_cast< ::sal_Int32 >(aLeft.Top() - m_nViewOffset),
     974             :                                         nWidth,
     975           0 :                                         static_cast< ::sal_Int32 >(aLeft.Bottom()
     976           0 :                                                                     - aLeft.Top()));
     977             :             // XXX  numeric overflow (4x)
     978             :     }
     979           0 :     return aBounds;
     980             : }
     981             : 
     982           0 : ::sal_Int32 Document::retrieveCharacterIndex(ParagraphImpl const * pParagraph,
     983             :                                              ::css::awt::Point const & rPoint)
     984             : {
     985           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
     986           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
     987           0 :     ::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           0 :                                             static_cast< long >(rPoint.Y))));
     991             :         // XXX  numeric overflow (2x)
     992           0 :     return aPaM.GetPara() == nNumber
     993           0 :         ? static_cast< ::sal_Int32 >(aPaM.GetIndex()) : -1;
     994             :         // XXX  numeric overflow
     995             : }
     996             : 
     997             : ::css::uno::Sequence< ::css::beans::PropertyValue >
     998           0 : Document::retrieveCharacterAttributes(
     999             :     ParagraphImpl const * pParagraph, ::sal_Int32 nIndex,
    1000             :     const ::css::uno::Sequence< OUString >& aRequestedAttributes)
    1001             : {
    1002           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1003           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
    1004           0 :     ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1005             :         // XXX  numeric overflow
    1006           0 :     if (nIndex < 0 || nIndex >= m_rEngine.GetText(nNumber).Len())
    1007             :         throw ::css::lang::IndexOutOfBoundsException(
    1008             :             "textwindowaccessibility.cxx:"
    1009             :             " Document::retrieveCharacterAttributes",
    1010           0 :             static_cast< ::css::uno::XWeak * >(this));
    1011             : 
    1012             :     // retrieve default attributes
    1013           0 :     tPropValMap aCharAttrSeq;
    1014           0 :     retrieveDefaultAttributesImpl( pParagraph, aRequestedAttributes, aCharAttrSeq );
    1015             : 
    1016             :     // retrieve run attributes
    1017           0 :     tPropValMap aRunAttrSeq;
    1018           0 :     retrieveRunAttributesImpl( pParagraph, nIndex, aRequestedAttributes, aRunAttrSeq );
    1019             : 
    1020             :     // merge default and run attributes
    1021           0 :     for ( tPropValMap::const_iterator aRunIter  = aRunAttrSeq.begin();
    1022           0 :           aRunIter != aRunAttrSeq.end();
    1023             :           ++aRunIter )
    1024             :     {
    1025           0 :         aCharAttrSeq[ aRunIter->first ] = aRunIter->second;
    1026             :     }
    1027             : 
    1028           0 :     return convertHashMapToSequence( aCharAttrSeq );
    1029             : }
    1030             : 
    1031           0 : void Document::retrieveDefaultAttributesImpl(
    1032             :     ParagraphImpl const * pParagraph,
    1033             :     const ::css::uno::Sequence< OUString >& RequestedAttributes,
    1034             :     tPropValMap& rDefAttrSeq)
    1035             : {
    1036             :     // default attributes are not supported by text engine
    1037             :     (void) pParagraph;
    1038             :     (void) RequestedAttributes;
    1039             :     (void) rDefAttrSeq;
    1040           0 : }
    1041             : 
    1042             : ::css::uno::Sequence< ::css::beans::PropertyValue >
    1043           0 : Document::retrieveDefaultAttributes(
    1044             :     ParagraphImpl const * pParagraph,
    1045             :     const ::css::uno::Sequence< OUString >& RequestedAttributes)
    1046             : {
    1047           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
    1048           0 :     ::osl::MutexGuard aInternalGuard( GetMutex() );
    1049             : 
    1050           0 :     tPropValMap aDefAttrSeq;
    1051           0 :     retrieveDefaultAttributesImpl( pParagraph, RequestedAttributes, aDefAttrSeq );
    1052           0 :     return convertHashMapToSequence( aDefAttrSeq );
    1053             : }
    1054             : 
    1055             : // static
    1056             : ::css::uno::Sequence< ::css::beans::PropertyValue >
    1057           0 : Document::convertHashMapToSequence(tPropValMap& rAttrSeq)
    1058             : {
    1059           0 :     ::css::uno::Sequence< ::css::beans::PropertyValue > aValues( rAttrSeq.size() );
    1060           0 :     ::css::beans::PropertyValue* pValues = aValues.getArray();
    1061           0 :     ::sal_Int32 i = 0;
    1062           0 :     for ( tPropValMap::const_iterator aIter  = rAttrSeq.begin();
    1063           0 :           aIter != rAttrSeq.end();
    1064             :           ++aIter )
    1065             :     {
    1066           0 :         pValues[i] = aIter->second;
    1067           0 :         ++i;
    1068             :     }
    1069           0 :     return aValues;
    1070             : }
    1071             : 
    1072           0 : void Document::retrieveRunAttributesImpl(
    1073             :     ParagraphImpl const * pParagraph, ::sal_Int32 Index,
    1074             :     const ::css::uno::Sequence< OUString >& RequestedAttributes,
    1075             :     tPropValMap& rRunAttrSeq)
    1076             : {
    1077           0 :     ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
    1078           0 :     ::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           0 :               m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTCOLOR ) );
    1084             :     ::TextAttribFontWeight const * pWeight
    1085             :           = static_cast< ::TextAttribFontWeight const * >(
    1086           0 :               m_rEngine.FindAttrib( aPaM, TEXTATTR_FONTWEIGHT ) );
    1087           0 :     tPropValMap aRunAttrSeq;
    1088           0 :     if ( pColor )
    1089             :     {
    1090           0 :         ::css::beans::PropertyValue aPropVal;
    1091           0 :         aPropVal.Name = "CharColor";
    1092           0 :         aPropVal.Handle = -1;
    1093           0 :         aPropVal.Value = mapFontColor( pColor->GetColor() );
    1094           0 :         aPropVal.State = ::css::beans::PropertyState_DIRECT_VALUE;
    1095           0 :         aRunAttrSeq[ aPropVal.Name ] = aPropVal;
    1096             :     }
    1097           0 :     if ( pWeight )
    1098             :     {
    1099           0 :         ::css::beans::PropertyValue aPropVal;
    1100           0 :         aPropVal.Name = "CharWeight";
    1101           0 :         aPropVal.Handle = -1;
    1102           0 :         aPropVal.Value = mapFontWeight( pWeight->getFontWeight() );
    1103           0 :         aPropVal.State = ::css::beans::PropertyState_DIRECT_VALUE;
    1104           0 :         aRunAttrSeq[ aPropVal.Name ] = aPropVal;
    1105             :     }
    1106           0 :     if ( RequestedAttributes.getLength() == 0 )
    1107             :     {
    1108           0 :         rRunAttrSeq = aRunAttrSeq;
    1109             :     }
    1110             :     else
    1111             :     {
    1112           0 :         const OUString* pReqAttrs = RequestedAttributes.getConstArray();
    1113           0 :         const ::sal_Int32 nLength = RequestedAttributes.getLength();
    1114           0 :         for ( ::sal_Int32 i = 0; i < nLength; ++i )
    1115             :         {
    1116           0 :             tPropValMap::iterator aIter = aRunAttrSeq.find( pReqAttrs[i] );
    1117           0 :             if ( aIter != aRunAttrSeq.end() )
    1118             :             {
    1119           0 :                 rRunAttrSeq[ (*aIter).first ] = (*aIter).second;
    1120             :             }
    1121             :         }
    1122           0 :     }
    1123           0 : }
    1124             : 
    1125             : ::css::uno::Sequence< ::css::beans::PropertyValue >
    1126           0 : Document::retrieveRunAttributes(
    1127             :     ParagraphImpl const * pParagraph, ::sal_Int32 Index,
    1128             :     const ::css::uno::Sequence< OUString >& RequestedAttributes)
    1129             : {
    1130           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
    1131           0 :     ::osl::MutexGuard aInternalGuard( GetMutex() );
    1132           0 :     ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
    1133             :         // XXX  numeric overflow
    1134           0 :     if ( Index < 0 || Index >= m_rEngine.GetText(nNumber).Len() )
    1135             :         throw ::css::lang::IndexOutOfBoundsException(
    1136             :             "textwindowaccessibility.cxx:"
    1137             :             " Document::retrieveRunAttributes",
    1138           0 :             static_cast< ::css::uno::XWeak * >( this ) );
    1139             : 
    1140           0 :     tPropValMap aRunAttrSeq;
    1141           0 :     retrieveRunAttributesImpl( pParagraph, Index, RequestedAttributes, aRunAttrSeq );
    1142           0 :     return convertHashMapToSequence( aRunAttrSeq );
    1143             : }
    1144             : 
    1145           0 : void Document::changeParagraphText(ParagraphImpl * pParagraph,
    1146             :                                    OUString const & rText)
    1147             : {
    1148           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1149             :     {
    1150           0 :         ::osl::MutexGuard aInternalGuard(GetMutex());
    1151           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1152             :             // XXX  numeric overflow
    1153           0 :         changeParagraphText(nNumber, 0, m_rEngine.GetTextLen(nNumber), false,
    1154           0 :                             false, rText);
    1155           0 :     }
    1156           0 : }
    1157             : 
    1158           0 : void Document::changeParagraphText(ParagraphImpl * pParagraph,
    1159             :                                    ::sal_Int32 nBegin, ::sal_Int32 nEnd,
    1160             :                                    bool bCut, bool bPaste,
    1161             :                                    OUString const & rText)
    1162             : {
    1163           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1164             :     {
    1165           0 :         ::osl::MutexGuard aInternalGuard(GetMutex());
    1166           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1167             :             // XXX  numeric overflow
    1168           0 :         if (nBegin < 0 || nBegin > nEnd
    1169           0 :             || nEnd > m_rEngine.GetText(nNumber).Len())
    1170             :             throw ::css::lang::IndexOutOfBoundsException(
    1171             :                 "textwindowaccessibility.cxx:"
    1172             :                 " Document::changeParagraphText",
    1173           0 :                 static_cast< ::css::uno::XWeak * >(this));
    1174             :         changeParagraphText(nNumber, static_cast< ::sal_uInt16 >(nBegin),
    1175           0 :                             static_cast< ::sal_uInt16 >(nEnd), bCut, bPaste, rText);
    1176             :             // XXX  numeric overflow (2x)
    1177           0 :     }
    1178           0 : }
    1179             : 
    1180           0 : void Document::copyParagraphText(ParagraphImpl const * pParagraph,
    1181             :                                  ::sal_Int32 nBegin, ::sal_Int32 nEnd)
    1182             : {
    1183           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1184             :     {
    1185           0 :         ::osl::MutexGuard aInternalGuard(GetMutex());
    1186           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1187             :             // XXX  numeric overflow
    1188           0 :         if (nBegin < 0 || nBegin > nEnd
    1189           0 :             || nEnd > m_rEngine.GetText(nNumber).Len())
    1190             :             throw ::css::lang::IndexOutOfBoundsException(
    1191             :                 "textwindowaccessibility.cxx:"
    1192             :                 " Document::copyParagraphText",
    1193           0 :                 static_cast< ::css::uno::XWeak * >(this));
    1194             :         m_rView.SetSelection(
    1195             :             ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
    1196           0 :                             ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
    1197             :             // XXX  numeric overflow (2x)
    1198           0 :         m_rView.Copy();
    1199           0 :     }
    1200           0 : }
    1201             : 
    1202           0 : void Document::changeParagraphAttributes(
    1203             :     ParagraphImpl * pParagraph, ::sal_Int32 nBegin, ::sal_Int32 nEnd,
    1204             :     ::css::uno::Sequence< ::css::beans::PropertyValue > const & rAttributeSet)
    1205             : {
    1206           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1207             :     {
    1208           0 :         ::osl::MutexGuard aInternalGuard(GetMutex());
    1209           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1210             :         // XXX  numeric overflow
    1211           0 :         if (nBegin < 0 || nBegin > nEnd
    1212           0 :             || nEnd > m_rEngine.GetText(nNumber).Len())
    1213             :             throw ::css::lang::IndexOutOfBoundsException(
    1214             :                 "textwindowaccessibility.cxx:"
    1215             :                 " Document::changeParagraphAttributes",
    1216           0 :                 static_cast< ::css::uno::XWeak * >(this));
    1217             : 
    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           0 :         for (::sal_Int32 i = 0; i < rAttributeSet.getLength(); ++i)
    1222           0 :             if ( rAttributeSet[i].Name == "CharColor" )
    1223             :                 m_rEngine.SetAttrib(::TextAttribFontColor(
    1224           0 :                                         mapFontColor(rAttributeSet[i].Value)),
    1225             :                                     nNumber, static_cast< ::sal_uInt16 >(nBegin),
    1226           0 :                                     static_cast< ::sal_uInt16 >(nEnd));
    1227             :                     // XXX  numeric overflow (2x)
    1228           0 :             else if ( rAttributeSet[i].Name == "CharWeight" )
    1229             :                 m_rEngine.SetAttrib(::TextAttribFontWeight(
    1230           0 :                                         mapFontWeight(rAttributeSet[i].Value)),
    1231             :                                     nNumber, static_cast< ::sal_uInt16 >(nBegin),
    1232           0 :                                     static_cast< ::sal_uInt16 >(nEnd));
    1233             :                     // XXX  numeric overflow (2x)
    1234           0 :     }
    1235           0 : }
    1236             : 
    1237           0 : void Document::changeParagraphSelection(ParagraphImpl * pParagraph,
    1238             :                                         ::sal_Int32 nBegin, ::sal_Int32 nEnd)
    1239             : {
    1240           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1241             :     {
    1242           0 :         ::osl::MutexGuard aInternalGuard(GetMutex());
    1243           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >(pParagraph->getNumber());
    1244             :             // XXX  numeric overflow
    1245           0 :         if (nBegin < 0 || nBegin > nEnd
    1246           0 :             || nEnd > m_rEngine.GetText(nNumber).Len())
    1247             :             throw ::css::lang::IndexOutOfBoundsException(
    1248             :                 "textwindowaccessibility.cxx:"
    1249             :                 " Document::changeParagraphSelection",
    1250           0 :                 static_cast< ::css::uno::XWeak * >(this));
    1251             :         m_rView.SetSelection(
    1252             :             ::TextSelection(::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nBegin)),
    1253           0 :                             ::TextPaM(nNumber, static_cast< ::sal_uInt16 >(nEnd))));
    1254             :             // XXX  numeric overflow (2x)
    1255           0 :     }
    1256           0 : }
    1257             : 
    1258             : ::css::i18n::Boundary
    1259           0 : Document::retrieveParagraphLineBoundary( ParagraphImpl const * pParagraph,
    1260             :                                          ::sal_Int32 nIndex, ::sal_Int32 *pLineNo )
    1261             : {
    1262           0 :     ::css::i18n::Boundary aBoundary;
    1263           0 :     aBoundary.startPos = nIndex;
    1264           0 :     aBoundary.endPos = nIndex;
    1265             : 
    1266           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
    1267             :     {
    1268           0 :         ::osl::MutexGuard aInternalGuard( GetMutex() );
    1269           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
    1270           0 :         if ( nIndex < 0 || nIndex > m_rEngine.GetText( nNumber ).Len() )
    1271             :             throw ::css::lang::IndexOutOfBoundsException(
    1272             :                 "textwindowaccessibility.cxx:"
    1273             :                 " Document::retrieveParagraphLineBoundary",
    1274           0 :                 static_cast< ::css::uno::XWeak * >( this ) );
    1275           0 :         ::sal_Int32 nLineStart = 0;
    1276           0 :         ::sal_Int32 nLineEnd = 0;
    1277           0 :         ::sal_uInt16 nLineCount = m_rEngine.GetLineCount( nNumber );
    1278           0 :         for ( ::sal_uInt16 nLine = 0; nLine < nLineCount; ++nLine )
    1279             :         {
    1280             :             ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
    1281           0 :                 m_rEngine.GetLineLen( nNumber, nLine ) );
    1282           0 :             nLineStart = nLineEnd;
    1283           0 :             nLineEnd += nLineLength;
    1284           0 :             if ( nIndex >= nLineStart && ( ( nLine == nLineCount - 1 ) ? nIndex <= nLineEnd : nIndex < nLineEnd ) )
    1285             :             {
    1286           0 :                 aBoundary.startPos = nLineStart;
    1287           0 :                 aBoundary.endPos = nLineEnd;
    1288           0 :                 if( pLineNo )
    1289           0 :                     pLineNo[0] = nLine;
    1290           0 :                 break;
    1291             :             }
    1292           0 :         }
    1293             :     }
    1294             : 
    1295           0 :     return aBoundary;
    1296             : }
    1297             : 
    1298             : ::css::i18n::Boundary
    1299           0 : Document::retrieveParagraphBoundaryOfLine( ParagraphImpl const * pParagraph,
    1300             :                                            ::sal_Int32 nLineNo )
    1301             : {
    1302           0 :     ::css::i18n::Boundary aBoundary;
    1303           0 :     aBoundary.startPos = 0;
    1304           0 :     aBoundary.endPos = 0;
    1305             : 
    1306           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard( getExternalLock() );
    1307             :     {
    1308           0 :         ::osl::MutexGuard aInternalGuard( GetMutex() );
    1309           0 :         ::sal_uLong nNumber = static_cast< ::sal_uLong >( pParagraph->getNumber() );
    1310           0 :         if ( nLineNo >= m_rEngine.GetLineCount( nNumber ) )
    1311             :             throw ::css::lang::IndexOutOfBoundsException(
    1312             :                 "textwindowaccessibility.cxx:"
    1313             :                 " Document::retrieveParagraphBoundaryOfLine",
    1314           0 :                 static_cast< ::css::uno::XWeak * >( this ) );
    1315           0 :         ::sal_Int32 nLineStart = 0;
    1316           0 :         ::sal_Int32 nLineEnd = 0;
    1317           0 :         for ( ::sal_uInt16 nLine = 0; nLine <= nLineNo; ++nLine )
    1318             :         {
    1319             :             ::sal_Int32 nLineLength = static_cast< ::sal_Int32 >(
    1320           0 :                 m_rEngine.GetLineLen( nNumber, nLine ) );
    1321           0 :             nLineStart = nLineEnd;
    1322           0 :             nLineEnd += nLineLength;
    1323             :         }
    1324             : 
    1325           0 :         aBoundary.startPos = nLineStart;
    1326           0 :         aBoundary.endPos = nLineEnd;
    1327             :     }
    1328             : 
    1329           0 :     return aBoundary;
    1330             : }
    1331             : 
    1332           0 : sal_Int32 Document::retrieveParagraphLineWithCursor( ParagraphImpl const * pParagraph )
    1333             : {
    1334           0 :     ::osl::Guard< ::comphelper::IMutex > aExternalGuard(getExternalLock());
    1335           0 :     ::osl::MutexGuard aInternalGuard(GetMutex());
    1336           0 :     ::TextSelection const & rSelection = m_rView.GetSelection();
    1337           0 :     Paragraphs::size_type nNumber = pParagraph->getNumber();
    1338           0 :     TextPaM aEndPaM( rSelection.GetEnd() );
    1339             : 
    1340           0 :     return aEndPaM.GetPara() == nNumber
    1341           0 :         ? m_rView.GetLineNumberOfCursorInSelection() : -1;
    1342             : }
    1343             : 
    1344             : 
    1345             : ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet >
    1346           0 : Document::retrieveParagraphRelationSet( ParagraphImpl const * pParagraph )
    1347             : {
    1348           0 :     ::osl::MutexGuard aInternalGuard( GetMutex() );
    1349             : 
    1350           0 :     ::utl::AccessibleRelationSetHelper* pRelationSetHelper = new ::utl::AccessibleRelationSetHelper();
    1351           0 :     ::css::uno::Reference< ::css::accessibility::XAccessibleRelationSet > xSet = pRelationSetHelper;
    1352             : 
    1353           0 :     Paragraphs::iterator aPara( m_xParagraphs->begin() + pParagraph->getNumber() );
    1354             : 
    1355           0 :     if ( aPara > m_aVisibleBegin && aPara < m_aVisibleEnd )
    1356             :     {
    1357           0 :         ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > aSequence(1);
    1358           0 :         aSequence[0] = getAccessibleChild( aPara - 1 );
    1359           0 :         ::css::accessibility::AccessibleRelation aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_FROM, aSequence );
    1360           0 :         pRelationSetHelper->AddRelation( aRelation );
    1361             :     }
    1362             : 
    1363           0 :     if ( aPara >= m_aVisibleBegin && aPara < m_aVisibleEnd -1 )
    1364             :     {
    1365           0 :         ::css::uno::Sequence< ::css::uno::Reference< ::css::uno::XInterface > > aSequence(1);
    1366           0 :         aSequence[0] = getAccessibleChild( aPara + 1 );
    1367           0 :         ::css::accessibility::AccessibleRelation aRelation( ::css::accessibility::AccessibleRelationType::CONTENT_FLOWS_TO, aSequence );
    1368           0 :         pRelationSetHelper->AddRelation( aRelation );
    1369             :     }
    1370             : 
    1371           0 :     return xSet;
    1372             : }
    1373             : 
    1374           0 : void Document::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
    1375             : {
    1376           0 :     switch ( rVclWindowEvent.GetId() )
    1377             :     {
    1378             :         case VCLEVENT_WINDOW_GETFOCUS:
    1379             :         case VCLEVENT_WINDOW_LOSEFOCUS:
    1380             :         {
    1381             :             // #107179# if our parent is a compound control (e.g. MultiLineEdit),
    1382             :             // suppress the window focus events here
    1383           0 :             if ( !m_bCompoundControlChild )
    1384           0 :                 VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
    1385             :         }
    1386           0 :         break;
    1387             :         default:
    1388           0 :             VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
    1389             :     }
    1390           0 : }
    1391             : 
    1392             : // virtual
    1393           0 : ::sal_Int32 SAL_CALL Document::getAccessibleChildCount()
    1394             :     throw (::css::uno::RuntimeException)
    1395             : {
    1396           0 :     ::comphelper::OExternalLockGuard aGuard(this);
    1397           0 :     init();
    1398           0 :     return m_aVisibleEnd - m_aVisibleBegin;
    1399             : }
    1400             : 
    1401             : // virtual
    1402             : ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
    1403           0 : Document::getAccessibleChild(::sal_Int32 i)
    1404             :     throw (::css::lang::IndexOutOfBoundsException,
    1405             :            ::css::uno::RuntimeException)
    1406             : {
    1407           0 :     ::comphelper::OExternalLockGuard aGuard(this);
    1408           0 :     init();
    1409           0 :     if (i < 0 || i >= m_aVisibleEnd - m_aVisibleBegin)
    1410             :         throw ::css::lang::IndexOutOfBoundsException(
    1411             :             "textwindowaccessibility.cxx:"
    1412             :             " Document::getAccessibleChild",
    1413           0 :             static_cast< ::css::uno::XWeak * >(this));
    1414             :     return getAccessibleChild(m_aVisibleBegin
    1415           0 :                               + static_cast< Paragraphs::size_type >(i));
    1416             : }
    1417             : 
    1418             : // virtual
    1419           0 : ::sal_Int16 SAL_CALL Document::getAccessibleRole()
    1420             :     throw (::css::uno::RuntimeException)
    1421             : {
    1422           0 :     return ::css::accessibility::AccessibleRole::TEXT_FRAME;
    1423             : }
    1424             : 
    1425             : // virtual
    1426             : ::css::uno::Reference< ::css::accessibility::XAccessible > SAL_CALL
    1427           0 : Document::getAccessibleAtPoint(::css::awt::Point const & rPoint)
    1428             :     throw (::css::uno::RuntimeException)
    1429             : {
    1430           0 :     ::comphelper::OExternalLockGuard aGuard(this);
    1431           0 :     init();
    1432           0 :     if (rPoint.X >= 0
    1433           0 :         && rPoint.X < m_rView.GetWindow()->GetOutputSizePixel().Width()
    1434             :         && rPoint.Y >= 0 && rPoint.Y < m_nViewHeight)
    1435             :     {
    1436           0 :         ::sal_Int32 nOffset = m_nViewOffset + rPoint.Y; // XXX  numeric overflow
    1437           0 :         ::sal_Int32 nPos = m_nViewOffset - m_nVisibleBeginOffset;
    1438           0 :         for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
    1439             :              ++aIt)
    1440             :         {
    1441           0 :             nPos += aIt->getHeight(); // XXX  numeric overflow
    1442           0 :             if (nOffset < nPos)
    1443           0 :                 return getAccessibleChild(aIt);
    1444             :         }
    1445             :     }
    1446           0 :     return 0;
    1447             : }
    1448             : 
    1449             : // virtual
    1450           0 : void SAL_CALL Document::disposing()
    1451             : {
    1452           0 :     m_aEngineListener.endListening();
    1453           0 :     m_aViewListener.endListening();
    1454           0 :     if (m_xParagraphs.get() != 0)
    1455           0 :         disposeParagraphs();
    1456           0 :     VCLXAccessibleComponent::disposing();
    1457           0 : }
    1458             : 
    1459             : // virtual
    1460           0 : void Document::Notify(::SfxBroadcaster &, ::SfxHint const & rHint)
    1461             : {
    1462           0 :     if (rHint.ISA(::TextHint))
    1463             :     {
    1464             :         ::TextHint const & rTextHint
    1465           0 :               = static_cast< ::TextHint const & >(rHint);
    1466           0 :         switch (rTextHint.GetId())
    1467             :         {
    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:
    1485             :             {
    1486           0 :                 ::osl::MutexGuard aInternalGuard(GetMutex());
    1487           0 :                 if (!isAlive())
    1488             :                     break;
    1489             : 
    1490           0 :                 m_aParagraphNotifications.push(rTextHint);
    1491           0 :                 break;
    1492             :             }
    1493             :         case TEXT_HINT_TEXTFORMATTED:
    1494             :         case TEXT_HINT_TEXTHEIGHTCHANGED:
    1495             :         case TEXT_HINT_MODIFIED:
    1496             :             {
    1497           0 :                 ::osl::MutexGuard aInternalGuard(GetMutex());
    1498           0 :                 if (!isAlive())
    1499             :                     break;
    1500           0 :                 handleParagraphNotifications();
    1501           0 :                 break;
    1502             :             }
    1503             :         case TEXT_HINT_VIEWSCROLLED:
    1504             :             {
    1505           0 :                 ::osl::MutexGuard aInternalGuard(GetMutex());
    1506           0 :                 if (!isAlive())
    1507             :                     break;
    1508           0 :                 handleParagraphNotifications();
    1509             : 
    1510             :                 ::sal_Int32 nOffset = static_cast< ::sal_Int32 >(
    1511           0 :                     m_rView.GetStartDocPos().Y());
    1512             :                     // XXX  numeric overflow
    1513           0 :                 if (nOffset != m_nViewOffset)
    1514             :                 {
    1515           0 :                     m_nViewOffset = nOffset;
    1516             : 
    1517             :                     Paragraphs::iterator aOldVisibleBegin(
    1518           0 :                         m_aVisibleBegin);
    1519           0 :                     Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
    1520             : 
    1521           0 :                     determineVisibleRange();
    1522             : 
    1523             :                     notifyVisibleRangeChanges(aOldVisibleBegin,
    1524             :                                                 aOldVisibleEnd,
    1525           0 :                                                 m_xParagraphs->end());
    1526             :                 }
    1527           0 :                 break;
    1528             :             }
    1529             :         case TEXT_HINT_VIEWSELECTIONCHANGED:
    1530             :             {
    1531           0 :                 ::osl::MutexGuard aInternalGuard(GetMutex());
    1532           0 :                 if (!isAlive())
    1533             :                     break;
    1534             : 
    1535           0 :                 if (m_aParagraphNotifications.empty())
    1536             :                 {
    1537           0 :                     handleSelectionChangeNotification();
    1538             :                 }
    1539             :                 else
    1540             :                 {
    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           0 :                     m_bSelectionChangedNotification = true;
    1552             :                 }
    1553           0 :                 break;
    1554             :             }
    1555             :         }
    1556             :     }
    1557           0 : }
    1558             : 
    1559           0 : IMPL_LINK(Document, WindowEventHandler, ::VclSimpleEvent *, pEvent)
    1560             : {
    1561           0 :     switch (pEvent->GetId())
    1562             :     {
    1563             :     case VCLEVENT_WINDOW_RESIZE:
    1564             :         {
    1565           0 :             ::osl::MutexGuard aInternalGuard(GetMutex());
    1566           0 :             if (!isAlive())
    1567             :                 break;
    1568             : 
    1569             :             ::sal_Int32 nHeight = static_cast< ::sal_Int32 >(
    1570           0 :                 m_rView.GetWindow()->GetOutputSizePixel().Height());
    1571             :                 // XXX  numeric overflow
    1572           0 :             if (nHeight != m_nViewHeight)
    1573             :             {
    1574           0 :                 m_nViewHeight = nHeight;
    1575             : 
    1576           0 :                 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
    1577           0 :                 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
    1578             : 
    1579           0 :                 determineVisibleRange();
    1580             : 
    1581             :                 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
    1582           0 :                                             m_xParagraphs->end());
    1583             :             }
    1584           0 :             break;
    1585             :         }
    1586             :     case VCLEVENT_WINDOW_GETFOCUS:
    1587             :         {
    1588           0 :             ::osl::MutexGuard aInternalGuard(GetMutex());
    1589           0 :             if (!isAlive())
    1590             :                 break;
    1591             : 
    1592           0 :             if (m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
    1593             :             {
    1594             :                 ::rtl::Reference< ParagraphImpl > xParagraph(
    1595           0 :                     getParagraph(m_aFocused));
    1596           0 :                 if (xParagraph.is())
    1597             :                     xParagraph->notifyEvent(
    1598             :                         ::css::accessibility::AccessibleEventId::
    1599             :                         STATE_CHANGED,
    1600             :                         ::css::uno::Any(),
    1601             :                         ::css::uno::makeAny(
    1602             :                             ::css::accessibility::AccessibleStateType::
    1603           0 :                             FOCUSED));
    1604             :             }
    1605           0 :             break;
    1606             :         }
    1607             :     case VCLEVENT_WINDOW_LOSEFOCUS:
    1608             :         {
    1609           0 :             ::osl::MutexGuard aInternalGuard(GetMutex());
    1610           0 :             if (!isAlive())
    1611             :                 break;
    1612             : 
    1613           0 :             if (m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
    1614             :             {
    1615             :                 ::rtl::Reference< ParagraphImpl > xParagraph(
    1616           0 :                     getParagraph(m_aFocused));
    1617           0 :                 if (xParagraph.is())
    1618             :                     xParagraph->notifyEvent(
    1619             :                         ::css::accessibility::AccessibleEventId::
    1620             :                         STATE_CHANGED,
    1621             :                         ::css::uno::makeAny(
    1622             :                             ::css::accessibility::AccessibleStateType::
    1623             :                             FOCUSED),
    1624           0 :                         ::css::uno::Any());
    1625             :             }
    1626           0 :             break;
    1627             :         }
    1628             :     }
    1629           0 :     return 0;
    1630             : }
    1631             : 
    1632           0 : void Document::init()
    1633             : {
    1634           0 :     if (m_xParagraphs.get() == 0)
    1635             :     {
    1636           0 :         ::sal_uLong nCount = m_rEngine.GetParagraphCount();
    1637             :         SAL_WNODEPRECATED_DECLARATIONS_PUSH
    1638           0 :         ::std::auto_ptr< Paragraphs > p(new Paragraphs);
    1639             :         SAL_WNODEPRECATED_DECLARATIONS_POP
    1640           0 :         p->reserve(static_cast< Paragraphs::size_type >(nCount));
    1641             :             // numeric overflow is harmless here
    1642           0 :         for (::sal_uLong i = 0; i < nCount; ++i)
    1643             :             p->push_back(ParagraphInfo(static_cast< ::sal_Int32 >(
    1644           0 :                                            m_rEngine.GetTextHeight(i))));
    1645             :                 // XXX  numeric overflow
    1646             :         m_nViewOffset = static_cast< ::sal_Int32 >(
    1647           0 :             m_rView.GetStartDocPos().Y()); // XXX  numeric overflow
    1648             :         m_nViewHeight = static_cast< ::sal_Int32 >(
    1649           0 :             m_rView.GetWindow()->GetOutputSizePixel().Height());
    1650             :             // XXX  numeric overflow
    1651           0 :         m_xParagraphs = p;
    1652           0 :         determineVisibleRange();
    1653           0 :         m_nSelectionFirstPara = -1;
    1654           0 :         m_nSelectionFirstPos = -1;
    1655           0 :         m_nSelectionLastPara = -1;
    1656           0 :         m_nSelectionLastPos = -1;
    1657           0 :         m_aFocused = m_xParagraphs->end();
    1658           0 :         m_bSelectionChangedNotification = false;
    1659           0 :         m_aEngineListener.startListening(m_rEngine);
    1660           0 :         m_aViewListener.startListening(*m_rView.GetWindow());
    1661             :     }
    1662           0 : }
    1663             : 
    1664             : ::rtl::Reference< ParagraphImpl >
    1665           0 : Document::getParagraph(Paragraphs::iterator const & rIt)
    1666             : {
    1667             :     return static_cast< ParagraphImpl * >(
    1668             :         ::css::uno::Reference< ::css::accessibility::XAccessible >(
    1669           0 :             rIt->getParagraph()).get());
    1670             : }
    1671             : 
    1672             : ::css::uno::Reference< ::css::accessibility::XAccessible >
    1673           0 : Document::getAccessibleChild(Paragraphs::iterator const & rIt)
    1674             : {
    1675             :     ::css::uno::Reference< ::css::accessibility::XAccessible > xParagraph(
    1676           0 :         rIt->getParagraph());
    1677           0 :     if (!xParagraph.is())
    1678             :     {
    1679           0 :         xParagraph = new Paragraph(this, rIt - m_xParagraphs->begin());
    1680           0 :         rIt->setParagraph(xParagraph);
    1681             :     }
    1682           0 :     return xParagraph;
    1683             : }
    1684             : 
    1685           0 : void Document::determineVisibleRange()
    1686             : {
    1687           0 :     Paragraphs::iterator const aEnd = m_xParagraphs->end();
    1688             : 
    1689           0 :     m_aVisibleBegin = aEnd;
    1690           0 :     m_aVisibleEnd = aEnd;
    1691           0 :     m_nVisibleBeginOffset = 0;
    1692             : 
    1693           0 :     ::sal_Int32 nPos = 0;
    1694           0 :     for (Paragraphs::iterator aIt = m_xParagraphs->begin(); m_aVisibleEnd == aEnd && aIt != aEnd; ++aIt)
    1695             :     {
    1696           0 :         ::sal_Int32 const nOldPos = nPos;
    1697           0 :         nPos += aIt->getHeight(); // XXX  numeric overflow
    1698           0 :         if (m_aVisibleBegin == aEnd)
    1699             :         {
    1700           0 :             if (nPos >= m_nViewOffset)
    1701             :             {
    1702           0 :                 m_aVisibleBegin = aIt;
    1703           0 :                 m_nVisibleBeginOffset = m_nViewOffset - nOldPos;
    1704             :             }
    1705             :         }
    1706             :         else
    1707             :         {
    1708           0 :             if (nPos >= m_nViewOffset + m_nViewHeight) // XXX  numeric overflow
    1709             :             {
    1710           0 :                 m_aVisibleEnd = aIt;
    1711             :             }
    1712             :         }
    1713             :     }
    1714             : 
    1715             :     OSL_POSTCOND(
    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");
    1719           0 : }
    1720             : 
    1721           0 : void Document::notifyVisibleRangeChanges(
    1722             :     Paragraphs::iterator const & rOldVisibleBegin,
    1723             :     Paragraphs::iterator const & rOldVisibleEnd,
    1724             :     Paragraphs::iterator const & rInserted)
    1725             : {
    1726             :     // XXX  Replace this code that determines which paragraphs have changed from
    1727             :     // invisible to visible or vice versa with a better algorithm.
    1728           0 :     {for (Paragraphs::iterator aIt(rOldVisibleBegin); aIt != rOldVisibleEnd;
    1729             :           ++aIt)
    1730           0 :         if (aIt != rInserted
    1731           0 :             && (aIt < m_aVisibleBegin || aIt >= m_aVisibleEnd))
    1732             :             NotifyAccessibleEvent(
    1733             :                 ::css::accessibility::AccessibleEventId::
    1734             :                 CHILD,
    1735             :                 ::css::uno::makeAny(getAccessibleChild(aIt)),
    1736           0 :                 ::css::uno::Any());
    1737             :     }
    1738           0 :     {for (Paragraphs::iterator aIt(m_aVisibleBegin); aIt != m_aVisibleEnd;
    1739             :           ++aIt)
    1740           0 :         if (aIt == rInserted
    1741           0 :             || aIt < rOldVisibleBegin || aIt >= rOldVisibleEnd)
    1742             :             NotifyAccessibleEvent(
    1743             :                 ::css::accessibility::AccessibleEventId::
    1744             :                 CHILD,
    1745             :                 ::css::uno::Any(),
    1746           0 :                 ::css::uno::makeAny(getAccessibleChild(aIt)));
    1747             :     }
    1748           0 : }
    1749             : 
    1750             : void
    1751           0 : Document::changeParagraphText(::sal_uLong nNumber, ::sal_uInt16 nBegin, ::sal_uInt16 nEnd,
    1752             :                               bool bCut, bool bPaste,
    1753             :                               OUString const & rText)
    1754             : {
    1755             :     m_rView.SetSelection(::TextSelection(::TextPaM(nNumber, nBegin),
    1756           0 :                                          ::TextPaM(nNumber, nEnd)));
    1757           0 :     if (bCut)
    1758           0 :         m_rView.Cut();
    1759           0 :     else if (nBegin != nEnd)
    1760           0 :         m_rView.DeleteSelected();
    1761           0 :     if (bPaste)
    1762           0 :         m_rView.Paste();
    1763           0 :     else if (!rText.isEmpty())
    1764           0 :         m_rView.InsertText(rText);
    1765           0 : }
    1766             : 
    1767           0 : void Document::handleParagraphNotifications()
    1768             : {
    1769           0 :     while (!m_aParagraphNotifications.empty())
    1770             :     {
    1771           0 :         ::TextHint aHint(m_aParagraphNotifications.front());
    1772           0 :         m_aParagraphNotifications.pop();
    1773           0 :         switch (aHint.GetId())
    1774             :         {
    1775             :         case TEXT_HINT_PARAINSERTED:
    1776             :             {
    1777           0 :                 ::sal_uLong n = aHint.GetValue();
    1778             :                 OSL_ENSURE(n <= m_xParagraphs->size(),
    1779             :                            "bad TEXT_HINT_PARAINSERTED event");
    1780             : 
    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           0 :                     = m_aVisibleBegin - m_xParagraphs->begin();
    1786             :                 Paragraphs::size_type nOldVisibleEnd
    1787           0 :                     = m_aVisibleEnd - m_xParagraphs->begin();
    1788             :                 Paragraphs::size_type nOldFocused
    1789           0 :                     = m_aFocused - m_xParagraphs->begin();
    1790           0 :                 if (n <= nOldVisibleBegin)
    1791           0 :                     ++nOldVisibleBegin; // XXX  numeric overflow
    1792           0 :                 if (n <= nOldVisibleEnd)
    1793           0 :                     ++nOldVisibleEnd; // XXX  numeric overflow
    1794           0 :                 if (n <= nOldFocused)
    1795           0 :                     ++nOldFocused; // XXX  numeric overflow
    1796           0 :                 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionFirstPara)
    1797           0 :                     ++m_nSelectionFirstPara; // XXX  numeric overflow
    1798           0 :                 if (sal::static_int_cast<sal_Int32>(n) <= m_nSelectionLastPara)
    1799           0 :                     ++m_nSelectionLastPara; // XXX  numeric overflow
    1800             : 
    1801             :                 Paragraphs::iterator aIns(
    1802             :                     m_xParagraphs->insert(
    1803           0 :                         m_xParagraphs->begin() + n,
    1804             :                         ParagraphInfo(static_cast< ::sal_Int32 >(
    1805           0 :                                           m_rEngine.GetTextHeight(n)))));
    1806             :                     // XXX  numeric overflow (2x)
    1807             : 
    1808           0 :                 determineVisibleRange();
    1809           0 :                 m_aFocused = m_xParagraphs->begin() + nOldFocused;
    1810             : 
    1811           0 :                 for (Paragraphs::iterator aIt(aIns);;)
    1812             :                 {
    1813           0 :                     ++aIt;
    1814           0 :                     if (aIt == m_xParagraphs->end())
    1815             :                         break;
    1816             :                     ::rtl::Reference< ParagraphImpl > xParagraph(
    1817           0 :                         getParagraph(aIt));
    1818           0 :                     if (xParagraph.is())
    1819           0 :                         xParagraph->numberChanged(true);
    1820           0 :                 }
    1821             : 
    1822             :                 notifyVisibleRangeChanges(
    1823           0 :                     m_xParagraphs->begin() + nOldVisibleBegin,
    1824           0 :                     m_xParagraphs->begin() + nOldVisibleEnd, aIns);
    1825             :                 break;
    1826             :             }
    1827             :         case TEXT_HINT_PARAREMOVED:
    1828             :             {
    1829           0 :                 ::sal_uLong n = aHint.GetValue();
    1830           0 :                 if (n == TEXT_PARA_ALL)
    1831             :                 {
    1832           0 :                     {for (Paragraphs::iterator aIt(m_aVisibleBegin);
    1833           0 :                           aIt != m_aVisibleEnd; ++aIt)
    1834             :                         NotifyAccessibleEvent(
    1835             :                             ::css::accessibility::AccessibleEventId::
    1836             :                             CHILD,
    1837             :                             ::css::uno::makeAny(getAccessibleChild(aIt)),
    1838           0 :                             ::css::uno::Any());
    1839             :                     }
    1840           0 :                     disposeParagraphs();
    1841           0 :                     m_xParagraphs->clear();
    1842           0 :                     determineVisibleRange();
    1843           0 :                     m_nSelectionFirstPara = -1;
    1844           0 :                     m_nSelectionFirstPos = -1;
    1845           0 :                     m_nSelectionLastPara = -1;
    1846           0 :                     m_nSelectionLastPos = -1;
    1847           0 :                     m_aFocused = m_xParagraphs->end();
    1848             :                 }
    1849             :                 else
    1850             :                 {
    1851             :                     OSL_ENSURE(n < m_xParagraphs->size(),
    1852             :                                "Bad TEXT_HINT_PARAREMOVED event");
    1853             : 
    1854           0 :                     Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
    1855             :                         // numeric overflow cannot occur
    1856             : 
    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           0 :                         = m_aVisibleBegin - m_xParagraphs->begin();
    1862             :                     Paragraphs::size_type nOldVisibleEnd
    1863           0 :                         = m_aVisibleEnd - m_xParagraphs->begin();
    1864             :                     bool bWasVisible
    1865           0 :                         = nOldVisibleBegin <= n && n < nOldVisibleEnd;
    1866             :                     Paragraphs::size_type nOldFocused
    1867           0 :                         = m_aFocused - m_xParagraphs->begin();
    1868           0 :                     bool bWasFocused = aIt == m_aFocused;
    1869           0 :                     if (n < nOldVisibleBegin)
    1870           0 :                         --nOldVisibleBegin;
    1871           0 :                     if (n < nOldVisibleEnd)
    1872           0 :                         --nOldVisibleEnd;
    1873           0 :                     if (n < nOldFocused)
    1874           0 :                         --nOldFocused;
    1875           0 :                     if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionFirstPara)
    1876           0 :                         --m_nSelectionFirstPara;
    1877           0 :                     else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionFirstPara)
    1878             :                     {
    1879           0 :                         if (m_nSelectionFirstPara == m_nSelectionLastPara)
    1880             :                         {
    1881           0 :                             m_nSelectionFirstPara = -1;
    1882           0 :                             m_nSelectionFirstPos = -1;
    1883           0 :                             m_nSelectionLastPara = -1;
    1884           0 :                             m_nSelectionLastPos = -1;
    1885             :                         }
    1886             :                         else
    1887             :                         {
    1888           0 :                             ++m_nSelectionFirstPara;
    1889           0 :                             m_nSelectionFirstPos = 0;
    1890             :                         }
    1891             :                     }
    1892           0 :                     if (sal::static_int_cast<sal_Int32>(n) < m_nSelectionLastPara)
    1893           0 :                         --m_nSelectionLastPara;
    1894           0 :                     else if (sal::static_int_cast<sal_Int32>(n) == m_nSelectionLastPara)
    1895             :                     {
    1896             :                         OSL_ENSURE(m_nSelectionFirstPara < m_nSelectionLastPara,
    1897             :                                    "logic error");
    1898           0 :                         --m_nSelectionLastPara;
    1899           0 :                         m_nSelectionLastPos = 0x7FFFFFFF;
    1900             :                     }
    1901             : 
    1902             :                     ::css::uno::Reference< ::css::accessibility::XAccessible >
    1903           0 :                           xStrong;
    1904           0 :                     if (bWasVisible)
    1905           0 :                         xStrong = getAccessibleChild(aIt);
    1906             :                     ::css::uno::WeakReference<
    1907             :                           ::css::accessibility::XAccessible > xWeak(
    1908           0 :                               aIt->getParagraph());
    1909           0 :                     aIt = m_xParagraphs->erase(aIt);
    1910             : 
    1911           0 :                     determineVisibleRange();
    1912           0 :                     m_aFocused = bWasFocused ? m_xParagraphs->end()
    1913           0 :                         : m_xParagraphs->begin() + nOldFocused;
    1914             : 
    1915           0 :                     for (; aIt != m_xParagraphs->end(); ++aIt)
    1916             :                     {
    1917             :                         ::rtl::Reference< ParagraphImpl > xParagraph(
    1918           0 :                             getParagraph(aIt));
    1919           0 :                         if (xParagraph.is())
    1920           0 :                             xParagraph->numberChanged(false);
    1921           0 :                     }
    1922             : 
    1923           0 :                     if (bWasVisible)
    1924             :                         NotifyAccessibleEvent(
    1925             :                             ::css::accessibility::AccessibleEventId::
    1926             :                             CHILD,
    1927             :                             ::css::uno::makeAny(xStrong),
    1928           0 :                             ::css::uno::Any());
    1929             : 
    1930             :                     ::css::uno::Reference< ::css::lang::XComponent > xComponent(
    1931           0 :                         xWeak.get(), ::css::uno::UNO_QUERY);
    1932           0 :                     if (xComponent.is())
    1933           0 :                         xComponent->dispose();
    1934             : 
    1935             :                     notifyVisibleRangeChanges(
    1936           0 :                         m_xParagraphs->begin() + nOldVisibleBegin,
    1937           0 :                         m_xParagraphs->begin() + nOldVisibleEnd,
    1938           0 :                         m_xParagraphs->end());
    1939             :                 }
    1940           0 :                 break;
    1941             :             }
    1942             :         case TEXT_HINT_FORMATPARA:
    1943             :             {
    1944           0 :                 ::sal_uLong n = aHint.GetValue();
    1945             :                 OSL_ENSURE(n < m_xParagraphs->size(),
    1946             :                            "Bad TEXT_HINT_FORMATPARA event");
    1947             : 
    1948           0 :                 (*m_xParagraphs)[static_cast< Paragraphs::size_type >(n)].
    1949             :                     changeHeight(static_cast< ::sal_Int32 >(
    1950           0 :                                      m_rEngine.GetTextHeight(n)));
    1951             :                     // XXX  numeric overflow
    1952           0 :                 Paragraphs::iterator aOldVisibleBegin(m_aVisibleBegin);
    1953           0 :                 Paragraphs::iterator aOldVisibleEnd(m_aVisibleEnd);
    1954           0 :                 determineVisibleRange();
    1955             :                 notifyVisibleRangeChanges(aOldVisibleBegin, aOldVisibleEnd,
    1956           0 :                                           m_xParagraphs->end());
    1957             : 
    1958           0 :                 if (n < m_xParagraphs->size())
    1959             :                 {
    1960           0 :                     Paragraphs::iterator aIt(m_xParagraphs->begin() + n);
    1961           0 :                     ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(aIt));
    1962           0 :                     if (xParagraph.is())
    1963           0 :                         xParagraph->textChanged();
    1964             :                 }
    1965             :                 break;
    1966             :             }
    1967             :         default:
    1968             :             OSL_FAIL( "bad buffered hint");
    1969           0 :             break;
    1970             :         }
    1971           0 :     }
    1972           0 :     if (m_bSelectionChangedNotification)
    1973             :     {
    1974           0 :         m_bSelectionChangedNotification = false;
    1975           0 :         handleSelectionChangeNotification();
    1976             :     }
    1977           0 : }
    1978             : 
    1979           0 : void Document::handleSelectionChangeNotification()
    1980             : {
    1981           0 :     ::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           0 :           = static_cast< ::sal_Int32 >(rSelection.GetStart().GetPara());
    1987             :     ::sal_Int32 nNewFirstPos
    1988           0 :           = static_cast< ::sal_Int32 >(rSelection.GetStart().GetIndex());
    1989             :         // XXX  numeric overflow
    1990             :     ::sal_Int32 nNewLastPara
    1991           0 :           = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetPara());
    1992             :     ::sal_Int32 nNewLastPos
    1993           0 :           = static_cast< ::sal_Int32 >(rSelection.GetEnd().GetIndex());
    1994             :         // XXX  numeric overflow
    1995             : 
    1996             :     // Lose focus:
    1997           0 :     Paragraphs::iterator aIt(m_xParagraphs->begin() + nNewLastPara);
    1998           0 :     if (m_aFocused != m_xParagraphs->end() && m_aFocused != aIt
    1999           0 :         && m_aFocused >= m_aVisibleBegin && m_aFocused < m_aVisibleEnd)
    2000             :     {
    2001           0 :         ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(m_aFocused));
    2002           0 :         if (xParagraph.is())
    2003             :             xParagraph->notifyEvent(
    2004             :                 ::css::accessibility::AccessibleEventId::
    2005             :                 STATE_CHANGED,
    2006             :                 ::css::uno::makeAny(
    2007             :                     ::css::accessibility::AccessibleStateType::FOCUSED),
    2008           0 :                 ::css::uno::Any());
    2009             :     }
    2010             : 
    2011             :     // Gain focus and update cursor position:
    2012           0 :     if (aIt >= m_aVisibleBegin && aIt < m_aVisibleEnd
    2013           0 :         && (aIt != m_aFocused
    2014             :             || nNewLastPara != m_nSelectionLastPara
    2015             :             || nNewLastPos != m_nSelectionLastPos))
    2016             :     {
    2017           0 :         ::rtl::Reference< ParagraphImpl > xParagraph(getParagraph(aIt));
    2018           0 :         if (xParagraph.is())
    2019             :         {
    2020           0 :             if (aIt != m_aFocused)
    2021             :                 xParagraph->notifyEvent(
    2022             :                     ::css::accessibility::AccessibleEventId::
    2023             :                     STATE_CHANGED,
    2024             :                     ::css::uno::Any(),
    2025             :                     ::css::uno::makeAny(
    2026           0 :                         ::css::accessibility::AccessibleStateType::FOCUSED));
    2027           0 :             if (nNewLastPara != m_nSelectionLastPara
    2028             :                 || nNewLastPos != m_nSelectionLastPos)
    2029             :                 xParagraph->notifyEvent(
    2030             :                     ::css::accessibility::AccessibleEventId::
    2031             :                     CARET_CHANGED,
    2032             :                     ::css::uno::makeAny< ::sal_Int32 >(
    2033             :                         nNewLastPara == m_nSelectionLastPara
    2034             :                         ? m_nSelectionLastPos : 0),
    2035           0 :                     ::css::uno::makeAny(nNewLastPos));
    2036           0 :         }
    2037             :     }
    2038           0 :     m_aFocused = aIt;
    2039             : 
    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.)
    2044             : 
    2045           0 :     TextPaM aOldTextStart( static_cast< sal_uLong >( m_nSelectionFirstPara ), static_cast< sal_uInt16 >( m_nSelectionFirstPos ) );
    2046           0 :     TextPaM aOldTextEnd( static_cast< sal_uLong >( m_nSelectionLastPara ), static_cast< sal_uInt16 >( m_nSelectionLastPos ) );
    2047           0 :     TextPaM aNewTextStart( static_cast< sal_uLong >( nNewFirstPara ), static_cast< sal_uInt16 >( nNewFirstPos ) );
    2048           0 :     TextPaM aNewTextEnd( static_cast< sal_uLong >( nNewLastPara ), static_cast< sal_uInt16 >( nNewLastPos ) );
    2049             : 
    2050             :     // justify selections
    2051           0 :     justifySelection( aOldTextStart, aOldTextEnd );
    2052           0 :     justifySelection( aNewTextStart, aNewTextEnd );
    2053             : 
    2054             :     sal_Int32 nFirst1;
    2055             :     sal_Int32 nLast1;
    2056             :     sal_Int32 nFirst2;
    2057             :     sal_Int32 nLast2;
    2058             : 
    2059           0 :     if ( m_nSelectionFirstPara == -1 )
    2060             :     {
    2061             :         // old selection not initialized yet => notify events only for new selection (if not empty)
    2062           0 :         nFirst1 = aNewTextStart.GetPara();
    2063           0 :         nLast1 = aNewTextEnd.GetPara() + ( aNewTextStart != aNewTextEnd ? 1 : 0 );
    2064           0 :         nFirst2 = 0;
    2065           0 :         nLast2 = 0;
    2066             :     }
    2067           0 :     else if ( aOldTextStart == aOldTextEnd && aNewTextStart == aNewTextEnd )
    2068             :     {
    2069             :         // old and new selection empty => no events
    2070           0 :         nFirst1 = 0;
    2071           0 :         nLast1 = 0;
    2072           0 :         nFirst2 = 0;
    2073           0 :         nLast2 = 0;
    2074             :     }
    2075           0 :     else if ( aOldTextStart != aOldTextEnd && aNewTextStart == aNewTextEnd )
    2076             :     {
    2077             :         // old selection not empty + new selection empty => notify events only for old selection
    2078           0 :         nFirst1 = aOldTextStart.GetPara();
    2079           0 :         nLast1 = aOldTextEnd.GetPara() + 1;
    2080           0 :         nFirst2 = 0;
    2081           0 :         nLast2 = 0;
    2082             :     }
    2083           0 :     else if ( aOldTextStart == aOldTextEnd && aNewTextStart != aNewTextEnd )
    2084             :     {
    2085             :         // old selection empty + new selection not empty => notify events only for new selection
    2086           0 :         nFirst1 = aNewTextStart.GetPara();
    2087           0 :         nLast1 = aNewTextEnd.GetPara() + 1;
    2088           0 :         nFirst2 = 0;
    2089           0 :         nLast2 = 0;
    2090             :     }
    2091             :     else
    2092             :     {
    2093             :         // old and new selection not empty => notify events for the two ranges left and right of the overlap
    2094           0 :         ::std::vector< TextPaM > aTextPaMs(4);
    2095           0 :         aTextPaMs[0] = aOldTextStart;
    2096           0 :         aTextPaMs[1] = aOldTextEnd;
    2097           0 :         aTextPaMs[2] = aNewTextStart;
    2098           0 :         aTextPaMs[3] = aNewTextEnd;
    2099           0 :         ::std::sort( aTextPaMs.begin(), aTextPaMs.end() );
    2100             : 
    2101           0 :         nFirst1 = aTextPaMs[0].GetPara();
    2102           0 :         nLast1 = aTextPaMs[1].GetPara() + ( aTextPaMs[0] != aTextPaMs[1] ? 1 : 0 );
    2103             : 
    2104           0 :         nFirst2 = aTextPaMs[2].GetPara();
    2105           0 :         nLast2 = aTextPaMs[3].GetPara() + ( aTextPaMs[2] != aTextPaMs[3] ? 1 : 0 );
    2106             : 
    2107             :         // adjust overlapping ranges
    2108           0 :         if ( nLast1 > nFirst2 )
    2109           0 :             nLast1 = nFirst2;
    2110             :     }
    2111             : 
    2112             :     // notify selection changes
    2113           0 :     notifySelectionChange( nFirst1, nLast1 );
    2114           0 :     notifySelectionChange( nFirst2, nLast2 );
    2115             : 
    2116           0 :     m_nSelectionFirstPara = nNewFirstPara;
    2117           0 :     m_nSelectionFirstPos = nNewFirstPos;
    2118           0 :     m_nSelectionLastPara = nNewLastPara;
    2119           0 :     m_nSelectionLastPos = nNewLastPos;
    2120           0 : }
    2121             : 
    2122           0 : void Document::notifySelectionChange( sal_Int32 nFirst, sal_Int32 nLast )
    2123             : {
    2124           0 :     nFirst = std::max( nFirst, sal_Int32( 0 ) );
    2125           0 :     nLast = std::min( nLast, sal_Int32( m_xParagraphs->size() ) );
    2126           0 :     Paragraphs::iterator iFirst(m_xParagraphs->begin() + nFirst);
    2127           0 :     Paragraphs::iterator iLast(m_xParagraphs->begin() + nLast);
    2128           0 :     if ( iFirst < m_aVisibleBegin )
    2129           0 :         iFirst = m_aVisibleBegin;
    2130           0 :     if ( iLast > m_aVisibleEnd )
    2131           0 :         iLast = m_aVisibleEnd;
    2132           0 :     if ( iFirst < iLast )
    2133             :     {
    2134           0 :         for ( Paragraphs::iterator i = iFirst; i != iLast; i++ )
    2135             :         {
    2136           0 :             ::rtl::Reference< ParagraphImpl > xParagraph( getParagraph( i ) );
    2137           0 :             if ( xParagraph.is() )
    2138             :             {
    2139             :                 xParagraph->notifyEvent(
    2140             :                     ::css::accessibility::AccessibleEventId::SELECTION_CHANGED,
    2141           0 :                     ::css::uno::Any(), ::css::uno::Any() );
    2142             :                 xParagraph->notifyEvent(
    2143             :                     ::css::accessibility::AccessibleEventId::TEXT_SELECTION_CHANGED,
    2144           0 :                     ::css::uno::Any(), ::css::uno::Any() );
    2145             :             }
    2146           0 :         }
    2147             :     }
    2148           0 : }
    2149             : 
    2150           0 : void Document::justifySelection( TextPaM& rTextStart, TextPaM& rTextEnd )
    2151             : {
    2152           0 :     if ( rTextStart > rTextEnd )
    2153             :     {
    2154           0 :         TextPaM aTextPaM( rTextStart );
    2155           0 :         rTextStart = rTextEnd;
    2156           0 :         rTextEnd = aTextPaM;
    2157             :     }
    2158           0 : }
    2159             : 
    2160           0 : void Document::disposeParagraphs()
    2161             : {
    2162           0 :     for (Paragraphs::iterator aIt(m_xParagraphs->begin());
    2163           0 :          aIt != m_xParagraphs->end(); ++aIt)
    2164             :     {
    2165             :         ::css::uno::Reference< ::css::lang::XComponent > xComponent(
    2166           0 :             aIt->getParagraph().get(), ::css::uno::UNO_QUERY);
    2167           0 :         if (xComponent.is())
    2168           0 :             xComponent->dispose();
    2169           0 :     }
    2170           0 : }
    2171             : 
    2172             : // static
    2173           0 : ::css::uno::Any Document::mapFontColor(::Color const & rColor)
    2174             : {
    2175             :     return ::css::uno::makeAny(
    2176           0 :         static_cast< ::sal_Int32 >(COLORDATA_RGB(rColor.GetColor())));
    2177             :         // FIXME  keep transparency?
    2178             : }
    2179             : 
    2180             : // static
    2181           0 : ::Color Document::mapFontColor(::css::uno::Any const & rColor)
    2182             : {
    2183           0 :     ::sal_Int32 nColor = 0;
    2184           0 :     rColor >>= nColor;
    2185           0 :     return ::Color(static_cast< ::ColorData >(nColor));
    2186             : }
    2187             : 
    2188             : // static
    2189           0 : ::css::uno::Any Document::mapFontWeight(::FontWeight nWeight)
    2190             : {
    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           0 :     return ::css::uno::makeAny(aWeight[nWeight]);
    2206             : }
    2207             : 
    2208             : // static
    2209           0 : ::FontWeight Document::mapFontWeight(::css::uno::Any const & rWeight)
    2210             : {
    2211           0 :     float nWeight = ::css::awt::FontWeight::NORMAL;
    2212           0 :     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
    2222           0 :         : WEIGHT_BLACK;
    2223             : }
    2224             : 
    2225             : }
    2226             : 
    2227             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10