nss: upgrade to release 3.73
[LibreOffice.git] / starmath / source / accessibility.cxx
blobefc6bc691043c10c980542d8ea574a098386d57c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
21 #include <sal/log.hxx>
23 #include <memory>
25 #include <com/sun/star/accessibility/AccessibleRole.hpp>
26 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
27 #include <com/sun/star/accessibility/AccessibleTextType.hpp>
28 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <unotools/accessiblerelationsethelper.hxx>
32 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
33 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
34 #include <com/sun/star/i18n/WordType.hpp>
35 #include <unotools/accessiblestatesethelper.hxx>
36 #include <comphelper/accessibleeventnotifier.hxx>
37 #include <cppuhelper/supportsservice.hxx>
38 #include <osl/diagnose.h>
39 #include <svx/AccessibleTextHelper.hxx>
40 #include <vcl/svapp.hxx>
41 #include <vcl/window.hxx>
42 #include <vcl/unohelp2.hxx>
43 #include <vcl/settings.hxx>
45 #include <tools/gen.hxx>
46 #include <svl/itemset.hxx>
48 #include <editeng/editobj.hxx>
49 #include <editeng/editdata.hxx>
50 #include <editeng/editview.hxx>
51 #include <editeng/eeitem.hxx>
52 #include <editeng/outliner.hxx>
53 #include <editeng/unoedhlp.hxx>
56 #include "accessibility.hxx"
57 #include <document.hxx>
58 #include <view.hxx>
59 #include <strings.hrc>
60 #include <smmod.hxx>
62 using namespace com::sun::star;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::uno;
65 using namespace com::sun::star::accessibility;
68 static awt::Rectangle lcl_GetBounds( vcl::Window const *pWin )
70 // !! see VCLXAccessibleComponent::implGetBounds()
72 //! the coordinates returned are relative to the parent window !
73 //! Thus the top-left point may be different from (0, 0) !
75 awt::Rectangle aBounds;
76 if (pWin)
78 tools::Rectangle aRect = pWin->GetWindowExtentsRelative( nullptr );
79 aBounds.X = aRect.Left();
80 aBounds.Y = aRect.Top();
81 aBounds.Width = aRect.GetWidth();
82 aBounds.Height = aRect.GetHeight();
83 vcl::Window* pParent = pWin->GetAccessibleParentWindow();
84 if (pParent)
86 tools::Rectangle aParentRect = pParent->GetWindowExtentsRelative( nullptr );
87 awt::Point aParentScreenLoc( aParentRect.Left(), aParentRect.Top() );
88 aBounds.X -= aParentScreenLoc.X;
89 aBounds.Y -= aParentScreenLoc.Y;
92 return aBounds;
95 static awt::Point lcl_GetLocationOnScreen( vcl::Window const *pWin )
97 // !! see VCLXAccessibleComponent::getLocationOnScreen()
99 awt::Point aPos;
100 if (pWin)
102 tools::Rectangle aRect = pWin->GetWindowExtentsRelative( nullptr );
103 aPos.X = aRect.Left();
104 aPos.Y = aRect.Top();
106 return aPos;
110 SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow *pGraphicWin ) :
111 aAccName (SmResId(RID_DOCUMENTSTR)),
112 nClientId (0),
113 pWin (pGraphicWin)
115 OSL_ENSURE( pWin, "SmGraphicAccessible: window missing" );
118 SmGraphicAccessible::~SmGraphicAccessible()
123 SmDocShell * SmGraphicAccessible::GetDoc_Impl()
125 SmViewShell *pView = pWin ? pWin->GetView() : nullptr;
126 return pView ? pView->GetDoc() : nullptr;
129 OUString SmGraphicAccessible::GetAccessibleText_Impl()
131 OUString aTxt;
132 SmDocShell *pDoc = GetDoc_Impl();
133 if (pDoc)
134 aTxt = pDoc->GetAccessibleText();
135 return aTxt;
138 void SmGraphicAccessible::ClearWin()
140 pWin = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
142 if ( nClientId )
144 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
145 nClientId = 0;
149 void SmGraphicAccessible::LaunchEvent(
150 const sal_Int16 nAccessibleEventId,
151 const uno::Any &rOldVal,
152 const uno::Any &rNewVal)
154 AccessibleEventObject aEvt;
155 aEvt.Source = static_cast<XAccessible *>(this);
156 aEvt.EventId = nAccessibleEventId;
157 aEvt.OldValue = rOldVal;
158 aEvt.NewValue = rNewVal ;
160 // pass event on to event-listener's
161 if (nClientId)
162 comphelper::AccessibleEventNotifier::addEvent( nClientId, aEvt );
165 uno::Reference< XAccessibleContext > SAL_CALL SmGraphicAccessible::getAccessibleContext()
167 return this;
170 sal_Bool SAL_CALL SmGraphicAccessible::containsPoint( const awt::Point& aPoint )
172 //! the arguments coordinates are relative to the current window !
173 //! Thus the top-left point is (0, 0)
175 SolarMutexGuard aGuard;
176 if (!pWin)
177 throw RuntimeException();
179 Size aSz( pWin->GetSizePixel() );
180 return aPoint.X >= 0 && aPoint.Y >= 0 &&
181 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
184 uno::Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleAtPoint(
185 const awt::Point& aPoint )
187 SolarMutexGuard aGuard;
188 XAccessible *pRes = nullptr;
189 if (containsPoint( aPoint ))
190 pRes = this;
191 return pRes;
194 awt::Rectangle SAL_CALL SmGraphicAccessible::getBounds()
196 SolarMutexGuard aGuard;
197 if (!pWin)
198 throw RuntimeException();
199 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
200 "mismatch of window parent and accessible parent" );
201 return lcl_GetBounds( pWin );
204 awt::Point SAL_CALL SmGraphicAccessible::getLocation()
206 SolarMutexGuard aGuard;
207 if (!pWin)
208 throw RuntimeException();
209 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
210 "mismatch of window parent and accessible parent" );
211 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
212 return awt::Point( aRect.X, aRect.Y );
215 awt::Point SAL_CALL SmGraphicAccessible::getLocationOnScreen()
217 SolarMutexGuard aGuard;
218 if (!pWin)
219 throw RuntimeException();
220 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
221 "mismatch of window parent and accessible parent" );
222 return lcl_GetLocationOnScreen( pWin );
225 awt::Size SAL_CALL SmGraphicAccessible::getSize()
227 SolarMutexGuard aGuard;
228 if (!pWin)
229 throw RuntimeException();
230 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
231 "mismatch of window parent and accessible parent" );
233 Size aSz( pWin->GetSizePixel() );
234 #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
235 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
236 Size aSz2( aRect.Width, aRect.Height );
237 assert(aSz == aSz2 && "mismatch in width" );
238 #endif
239 return awt::Size( aSz.Width(), aSz.Height() );
242 void SAL_CALL SmGraphicAccessible::grabFocus()
244 SolarMutexGuard aGuard;
245 if (!pWin)
246 throw RuntimeException();
248 pWin->GrabFocus();
251 sal_Int32 SAL_CALL SmGraphicAccessible::getForeground()
253 SolarMutexGuard aGuard;
255 if (!pWin)
256 throw RuntimeException();
257 return static_cast<sal_Int32>(pWin->GetTextColor());
260 sal_Int32 SAL_CALL SmGraphicAccessible::getBackground()
262 SolarMutexGuard aGuard;
264 if (!pWin)
265 throw RuntimeException();
266 Wallpaper aWall( pWin->GetDisplayBackground() );
267 Color nCol;
268 if (aWall.IsBitmap() || aWall.IsGradient())
269 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor();
270 else
271 nCol = aWall.GetColor();
272 return static_cast<sal_Int32>(nCol);
275 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleChildCount()
277 return 0;
280 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleChild(
281 sal_Int32 /*i*/ )
283 throw IndexOutOfBoundsException(); // there is no child...
286 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleParent()
288 SolarMutexGuard aGuard;
289 if (!pWin)
290 throw RuntimeException();
292 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
293 OSL_ENSURE( pAccParent, "accessible parent missing" );
294 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
297 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleIndexInParent()
299 SolarMutexGuard aGuard;
300 sal_Int32 nIdx = -1;
301 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : nullptr;
302 if (pAccParent)
304 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
305 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
306 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
307 nIdx = i;
309 return nIdx;
312 sal_Int16 SAL_CALL SmGraphicAccessible::getAccessibleRole()
314 return AccessibleRole::DOCUMENT;
317 OUString SAL_CALL SmGraphicAccessible::getAccessibleDescription()
319 SolarMutexGuard aGuard;
320 SmDocShell *pDoc = GetDoc_Impl();
321 return pDoc ? pDoc->GetText() : OUString();
324 OUString SAL_CALL SmGraphicAccessible::getAccessibleName()
326 SolarMutexGuard aGuard;
327 return aAccName;
330 Reference< XAccessibleRelationSet > SAL_CALL SmGraphicAccessible::getAccessibleRelationSet()
332 SolarMutexGuard aGuard;
333 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
334 return xRelSet; // empty relation set
337 Reference< XAccessibleStateSet > SAL_CALL SmGraphicAccessible::getAccessibleStateSet()
339 SolarMutexGuard aGuard;
340 ::utl::AccessibleStateSetHelper *pStateSet =
341 new ::utl::AccessibleStateSetHelper;
343 Reference<XAccessibleStateSet> xStateSet( pStateSet );
345 if (!pWin)
346 pStateSet->AddState( AccessibleStateType::DEFUNC );
347 else
349 pStateSet->AddState( AccessibleStateType::ENABLED );
350 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
351 if (pWin->HasFocus())
352 pStateSet->AddState( AccessibleStateType::FOCUSED );
353 if (pWin->IsActive())
354 pStateSet->AddState( AccessibleStateType::ACTIVE );
355 if (pWin->IsVisible())
356 pStateSet->AddState( AccessibleStateType::SHOWING );
357 if (pWin->IsReallyVisible())
358 pStateSet->AddState( AccessibleStateType::VISIBLE );
359 if (COL_TRANSPARENT != pWin->GetBackground().GetColor())
360 pStateSet->AddState( AccessibleStateType::OPAQUE );
363 return xStateSet;
366 Locale SAL_CALL SmGraphicAccessible::getLocale()
368 SolarMutexGuard aGuard;
369 // should be the document language...
370 // We use the language of the localized symbol names here.
371 return Application::GetSettings().GetUILanguageTag().getLocale();
375 void SAL_CALL SmGraphicAccessible::addAccessibleEventListener(
376 const Reference< XAccessibleEventListener >& xListener )
378 if (xListener.is())
380 SolarMutexGuard aGuard;
381 if (pWin)
383 if (!nClientId)
384 nClientId = comphelper::AccessibleEventNotifier::registerClient( );
385 comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
390 void SAL_CALL SmGraphicAccessible::removeAccessibleEventListener(
391 const Reference< XAccessibleEventListener >& xListener )
393 if (!(xListener.is() && nClientId))
394 return;
396 SolarMutexGuard aGuard;
397 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener );
398 if ( !nListenerCount )
400 // no listeners anymore
401 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
402 // and at least to us not firing any events anymore, in case somebody calls
403 // NotifyAccessibleEvent, again
404 comphelper::AccessibleEventNotifier::revokeClient( nClientId );
405 nClientId = 0;
409 sal_Int32 SAL_CALL SmGraphicAccessible::getCaretPosition()
411 return 0;
414 sal_Bool SAL_CALL SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex )
416 SolarMutexGuard aGuard;
417 OUString aTxt( GetAccessibleText_Impl() );
418 if (nIndex >= aTxt.getLength())
419 throw IndexOutOfBoundsException();
420 return false;
423 sal_Unicode SAL_CALL SmGraphicAccessible::getCharacter( sal_Int32 nIndex )
425 SolarMutexGuard aGuard;
426 OUString aTxt( GetAccessibleText_Impl() );
427 if (nIndex >= aTxt.getLength())
428 throw IndexOutOfBoundsException();
429 return aTxt[nIndex];
432 Sequence< beans::PropertyValue > SAL_CALL SmGraphicAccessible::getCharacterAttributes(
433 sal_Int32 nIndex,
434 const uno::Sequence< OUString > & /*rRequestedAttributes*/ )
436 SolarMutexGuard aGuard;
437 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
438 if (0 > nIndex || nIndex >= nLen)
439 throw IndexOutOfBoundsException();
440 return Sequence< beans::PropertyValue >();
443 awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex )
445 SolarMutexGuard aGuard;
447 awt::Rectangle aRes;
449 if (!pWin)
450 throw RuntimeException();
452 // get accessible text
453 SmViewShell *pView = pWin->GetView();
454 SmDocShell *pDoc = pView ? pView->GetDoc() : nullptr;
455 if (!pDoc)
456 throw RuntimeException();
457 OUString aTxt( GetAccessibleText_Impl() );
458 if (0 > nIndex || nIndex > aTxt.getLength()) // aTxt.getLength() is valid
459 throw IndexOutOfBoundsException();
461 // find a reasonable rectangle for position aTxt.getLength().
462 bool bWasBehindText = (nIndex == aTxt.getLength());
463 if (bWasBehindText && nIndex)
464 --nIndex;
466 const SmNode *pTree = pDoc->GetFormulaTree();
467 const SmNode *pNode = pTree->FindNodeWithAccessibleIndex( nIndex );
468 //! pNode may be 0 if the index belongs to a char that was inserted
469 //! only for the accessible text!
470 if (pNode)
472 sal_Int32 nAccIndex = pNode->GetAccessibleIndex();
473 OSL_ENSURE( nAccIndex >= 0, "invalid accessible index" );
474 OSL_ENSURE( nIndex >= nAccIndex, "index out of range" );
476 OUStringBuffer aBuf;
477 pNode->GetAccessibleText(aBuf);
478 OUString aNodeText = aBuf.makeStringAndClear();
479 sal_Int32 nNodeIndex = nIndex - nAccIndex;
480 if (0 <= nNodeIndex && nNodeIndex < aNodeText.getLength())
482 // get appropriate rectangle
483 Point aOffset(pNode->GetTopLeft() - pTree->GetTopLeft());
484 Point aTLPos (pWin->GetFormulaDrawPos() + aOffset);
485 Size aSize (pNode->GetSize());
487 std::unique_ptr<tools::Long[]> pXAry(new tools::Long[ aNodeText.getLength() ]);
488 pWin->SetFont( pNode->GetFont() );
489 pWin->GetTextArray( aNodeText, pXAry.get(), 0, aNodeText.getLength() );
490 aTLPos.AdjustX(nNodeIndex > 0 ? pXAry[nNodeIndex - 1] : 0 );
491 aSize.setWidth( nNodeIndex > 0 ? pXAry[nNodeIndex] - pXAry[nNodeIndex - 1] : pXAry[nNodeIndex] );
492 pXAry.reset();
494 aTLPos = pWin->LogicToPixel( aTLPos );
495 aSize = pWin->LogicToPixel( aSize );
496 aRes.X = aTLPos.X();
497 aRes.Y = aTLPos.Y();
498 aRes.Width = aSize.Width();
499 aRes.Height = aSize.Height();
503 // take rectangle from last character and move it to the right
504 if (bWasBehindText)
505 aRes.X += aRes.Width;
507 return aRes;
510 sal_Int32 SAL_CALL SmGraphicAccessible::getCharacterCount()
512 SolarMutexGuard aGuard;
513 return GetAccessibleText_Impl().getLength();
516 sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoint )
518 SolarMutexGuard aGuard;
520 sal_Int32 nRes = -1;
521 if (pWin)
523 const SmNode *pTree = pWin->GetView()->GetDoc()->GetFormulaTree();
524 // can be NULL! e.g. if one clicks within the window already during loading of the
525 // document (before the parser even started)
526 if (!pTree)
527 return nRes;
529 // get position relative to formula draw position
530 Point aPos( aPoint.X, aPoint.Y );
531 aPos = pWin->PixelToLogic( aPos );
532 aPos -= pWin->GetFormulaDrawPos();
534 // if it was inside the formula then get the appropriate node
535 const SmNode *pNode = nullptr;
536 if (pTree->OrientedDist(aPos) <= 0)
537 pNode = pTree->FindRectClosestTo(aPos);
539 if (pNode)
541 // get appropriate rectangle
542 Point aOffset( pNode->GetTopLeft() - pTree->GetTopLeft() );
543 Point aTLPos ( aOffset );
544 Size aSize( pNode->GetSize() );
546 tools::Rectangle aRect( aTLPos, aSize );
547 if (aRect.IsInside( aPos ))
549 OSL_ENSURE( pNode->IsVisible(), "node is not a leaf" );
550 OUStringBuffer aBuf;
551 pNode->GetAccessibleText(aBuf);
552 OUString aTxt = aBuf.makeStringAndClear();
553 OSL_ENSURE( !aTxt.isEmpty(), "no accessible text available" );
555 tools::Long nNodeX = pNode->GetLeft();
557 std::unique_ptr<tools::Long[]> pXAry(new tools::Long[ aTxt.getLength() ]);
558 pWin->SetFont( pNode->GetFont() );
559 pWin->GetTextArray( aTxt, pXAry.get(), 0, aTxt.getLength() );
560 for (sal_Int32 i = 0; i < aTxt.getLength() && nRes == -1; ++i)
562 if (pXAry[i] + nNodeX > aPos.X())
563 nRes = i;
565 pXAry.reset();
566 OSL_ENSURE( nRes >= 0 && nRes < aTxt.getLength(), "index out of range" );
567 OSL_ENSURE( pNode->GetAccessibleIndex() >= 0,
568 "invalid accessible index" );
570 nRes = pNode->GetAccessibleIndex() + nRes;
574 return nRes;
577 OUString SAL_CALL SmGraphicAccessible::getSelectedText()
579 return OUString();
582 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionStart()
584 return -1;
587 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionEnd()
589 return -1;
592 sal_Bool SAL_CALL SmGraphicAccessible::setSelection(
593 sal_Int32 nStartIndex,
594 sal_Int32 nEndIndex )
596 SolarMutexGuard aGuard;
597 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
598 if (0 > nStartIndex || nStartIndex >= nLen ||
599 0 > nEndIndex || nEndIndex >= nLen)
600 throw IndexOutOfBoundsException();
601 return false;
604 OUString SAL_CALL SmGraphicAccessible::getText()
606 SolarMutexGuard aGuard;
607 return GetAccessibleText_Impl();
610 OUString SAL_CALL SmGraphicAccessible::getTextRange(
611 sal_Int32 nStartIndex,
612 sal_Int32 nEndIndex )
614 //!! nEndIndex may be the string length per definition of the interface !!
615 //!! text should be copied exclusive that end index though. And arguments
616 //!! may be switched.
618 SolarMutexGuard aGuard;
619 OUString aTxt( GetAccessibleText_Impl() );
620 sal_Int32 nStart = std::min(nStartIndex, nEndIndex);
621 sal_Int32 nEnd = std::max(nStartIndex, nEndIndex);
622 if ((nStart > aTxt.getLength()) ||
623 (nEnd > aTxt.getLength()))
624 throw IndexOutOfBoundsException();
625 return aTxt.copy( nStart, nEnd - nStart );
628 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType )
630 SolarMutexGuard aGuard;
631 OUString aTxt( GetAccessibleText_Impl() );
632 //!! nIndex is allowed to be the string length
633 if (nIndex > aTxt.getLength())
634 throw IndexOutOfBoundsException();
636 css::accessibility::TextSegment aResult;
637 aResult.SegmentStart = -1;
638 aResult.SegmentEnd = -1;
639 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
641 aResult.SegmentText = aTxt.copy(nIndex, 1);
642 aResult.SegmentStart = nIndex;
643 aResult.SegmentEnd = nIndex+1;
645 return aResult;
648 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType )
650 SolarMutexGuard aGuard;
651 OUString aTxt( GetAccessibleText_Impl() );
652 //!! nIndex is allowed to be the string length
653 if (nIndex > aTxt.getLength())
654 throw IndexOutOfBoundsException();
656 css::accessibility::TextSegment aResult;
657 aResult.SegmentStart = -1;
658 aResult.SegmentEnd = -1;
660 if ( (AccessibleTextType::CHARACTER == aTextType) && nIndex )
662 aResult.SegmentText = aTxt.copy(nIndex-1, 1);
663 aResult.SegmentStart = nIndex-1;
664 aResult.SegmentEnd = nIndex;
666 return aResult;
669 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType )
671 SolarMutexGuard aGuard;
672 OUString aTxt( GetAccessibleText_Impl() );
673 //!! nIndex is allowed to be the string length
674 if (nIndex > aTxt.getLength())
675 throw IndexOutOfBoundsException();
677 css::accessibility::TextSegment aResult;
678 aResult.SegmentStart = -1;
679 aResult.SegmentEnd = -1;
681 nIndex++; // text *behind*
682 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
684 aResult.SegmentText = aTxt.copy(nIndex, 1);
685 aResult.SegmentStart = nIndex;
686 aResult.SegmentEnd = nIndex+1;
688 return aResult;
691 sal_Bool SAL_CALL SmGraphicAccessible::copyText(
692 sal_Int32 nStartIndex,
693 sal_Int32 nEndIndex )
695 SolarMutexGuard aGuard;
696 bool bReturn = false;
698 if (!pWin)
699 throw RuntimeException();
701 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWin->GetClipboard();
702 if ( xClipboard.is() )
704 OUString sText( getTextRange(nStartIndex, nEndIndex) );
706 vcl::unohelper::TextDataObject* pDataObj = new vcl::unohelper::TextDataObject( sText );
707 SolarMutexReleaser aReleaser;
708 xClipboard->setContents( pDataObj, nullptr );
710 Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
711 if( xFlushableClipboard.is() )
712 xFlushableClipboard->flushClipboard();
714 bReturn = true;
718 return bReturn;
721 sal_Bool SAL_CALL SmGraphicAccessible::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType )
723 return false;
726 OUString SAL_CALL SmGraphicAccessible::getImplementationName()
728 return "SmGraphicAccessible";
731 sal_Bool SAL_CALL SmGraphicAccessible::supportsService(
732 const OUString& rServiceName )
734 return cppu::supportsService(this, rServiceName);
737 Sequence< OUString > SAL_CALL SmGraphicAccessible::getSupportedServiceNames()
739 return {
740 "css::accessibility::Accessible",
741 "css::accessibility::AccessibleComponent",
742 "css::accessibility::AccessibleContext",
743 "css::accessibility::AccessibleText"
748 SmEditSource::SmEditSource( SmEditAccessible &rAcc ) :
749 aViewFwd (rAcc),
750 aTextFwd (rAcc, *this),
751 aEditViewFwd(rAcc),
752 rEditAcc (rAcc)
756 SmEditSource::SmEditSource( const SmEditSource &rSrc ) :
757 SvxEditSource(),
758 aViewFwd (rSrc.rEditAcc),
759 aTextFwd (rSrc.rEditAcc, *this),
760 aEditViewFwd(rSrc.rEditAcc),
761 rEditAcc (rSrc.rEditAcc)
765 SmEditSource::~SmEditSource()
769 std::unique_ptr<SvxEditSource> SmEditSource::Clone() const
771 return std::unique_ptr<SvxEditSource>(new SmEditSource( *this ));
774 SvxTextForwarder* SmEditSource::GetTextForwarder()
776 return &aTextFwd;
779 SvxViewForwarder* SmEditSource::GetViewForwarder()
781 return &aViewFwd;
784 SvxEditViewForwarder* SmEditSource::GetEditViewForwarder( bool /*bCreate*/ )
786 return &aEditViewFwd;
789 void SmEditSource::UpdateData()
791 // would possibly only by needed if the XText interface is implemented
792 // and its text needs to be updated.
795 SfxBroadcaster & SmEditSource::GetBroadcaster() const
797 return const_cast<SmEditSource*>(this)->aBroadCaster;
800 SmViewForwarder::SmViewForwarder( SmEditAccessible &rAcc ) :
801 rEditAcc(rAcc)
805 SmViewForwarder::~SmViewForwarder()
809 bool SmViewForwarder::IsValid() const
811 return rEditAcc.GetEditView() != nullptr;
814 Point SmViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
816 EditView *pEditView = rEditAcc.GetEditView();
817 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
819 if( pOutDev )
821 MapMode aMapMode(pOutDev->GetMapMode());
822 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
823 MapMode(aMapMode.GetMapUnit())) );
824 aMapMode.SetOrigin(Point());
825 return pOutDev->LogicToPixel( aPoint, aMapMode );
828 return Point();
831 Point SmViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
833 EditView *pEditView = rEditAcc.GetEditView();
834 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
836 if( pOutDev )
838 MapMode aMapMode(pOutDev->GetMapMode());
839 aMapMode.SetOrigin(Point());
840 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
841 return OutputDevice::LogicToLogic( aPoint,
842 MapMode(aMapMode.GetMapUnit()),
843 rMapMode );
846 return Point();
850 SmTextForwarder::SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource) :
851 rEditAcc ( rAcc ),
852 rEditSource (rSource)
854 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
855 if (pEditEngine)
856 pEditEngine->SetNotifyHdl( LINK(this, SmTextForwarder, NotifyHdl) );
859 SmTextForwarder::~SmTextForwarder()
861 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
862 if (pEditEngine)
863 pEditEngine->SetNotifyHdl( Link<EENotify&,void>() );
866 IMPL_LINK(SmTextForwarder, NotifyHdl, EENotify&, rNotify, void)
868 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &rNotify );
869 if (aHint)
870 rEditSource.GetBroadcaster().Broadcast(*aHint);
873 sal_Int32 SmTextForwarder::GetParagraphCount() const
875 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
876 return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
879 sal_Int32 SmTextForwarder::GetTextLen( sal_Int32 nParagraph ) const
881 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
882 return pEditEngine ? pEditEngine->GetTextLen( nParagraph ) : 0;
885 OUString SmTextForwarder::GetText( const ESelection& rSel ) const
887 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
888 OUString aRet;
889 if (pEditEngine)
890 aRet = pEditEngine->GetText( rSel );
891 return convertLineEnd(aRet, GetSystemLineEnd());
894 SfxItemSet SmTextForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
896 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
897 assert(pEditEngine && "EditEngine missing");
898 if( rSel.nStartPara == rSel.nEndPara )
900 GetAttribsFlags nFlags = GetAttribsFlags::NONE;
901 switch( nOnlyHardAttrib )
903 case EditEngineAttribs::All:
904 nFlags = GetAttribsFlags::ALL;
905 break;
906 case EditEngineAttribs::OnlyHard:
907 nFlags = GetAttribsFlags::CHARATTRIBS;
908 break;
909 default:
910 SAL_WARN("starmath", "unknown flags for SmTextForwarder::GetAttribs");
913 return pEditEngine->GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
915 else
917 return pEditEngine->GetAttribs( rSel, nOnlyHardAttrib );
921 SfxItemSet SmTextForwarder::GetParaAttribs( sal_Int32 nPara ) const
923 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
924 assert(pEditEngine && "EditEngine missing");
926 SfxItemSet aSet( pEditEngine->GetParaAttribs( nPara ) );
928 sal_uInt16 nWhich = EE_PARA_START;
929 while( nWhich <= EE_PARA_END )
931 if( aSet.GetItemState( nWhich ) != SfxItemState::SET )
933 if( pEditEngine->HasParaAttrib( nPara, nWhich ) )
934 aSet.Put( pEditEngine->GetParaAttrib( nPara, nWhich ) );
936 nWhich++;
939 return aSet;
942 void SmTextForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
944 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
945 if (pEditEngine)
946 pEditEngine->SetParaAttribs( nPara, rSet );
949 SfxItemPool* SmTextForwarder::GetPool() const
951 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
952 return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : nullptr;
955 void SmTextForwarder::RemoveAttribs( const ESelection& rSelection )
957 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
958 if (pEditEngine)
959 pEditEngine->RemoveAttribs( rSelection, false/*bRemoveParaAttribs*/, 0 );
962 void SmTextForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
964 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
965 if (pEditEngine)
966 pEditEngine->GetPortions( nPara, rList );
969 void SmTextForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
971 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
972 if (pEditEngine)
973 pEditEngine->QuickInsertText( rText, rSel );
976 void SmTextForwarder::QuickInsertLineBreak( const ESelection& rSel )
978 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
979 if (pEditEngine)
980 pEditEngine->QuickInsertLineBreak( rSel );
983 void SmTextForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
985 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
986 if (pEditEngine)
987 pEditEngine->QuickInsertField( rFld, rSel );
990 void SmTextForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
992 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
993 if (pEditEngine)
994 pEditEngine->QuickSetAttribs( rSet, rSel );
997 bool SmTextForwarder::IsValid() const
999 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1000 // cannot reliably query EditEngine state
1001 // while in the middle of an update
1002 return pEditEngine && pEditEngine->GetUpdateMode();
1005 OUString SmTextForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor )
1007 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1008 return pEditEngine ? pEditEngine->CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor) : OUString();
1011 void SmTextForwarder::FieldClicked(const SvxFieldItem&)
1015 static SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
1017 std::vector<EECharAttrib> aAttribs;
1019 const SfxPoolItem* pLastItem = nullptr;
1021 SfxItemState eState = SfxItemState::DEFAULT;
1023 // check all paragraphs inside the selection
1024 for( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
1026 SfxItemState eParaState = SfxItemState::DEFAULT;
1028 // calculate start and endpos for this paragraph
1029 sal_Int32 nPos = 0;
1030 if( rSel.nStartPara == nPara )
1031 nPos = rSel.nStartPos;
1033 sal_Int32 nEndPos = rSel.nEndPos;
1034 if( rSel.nEndPara != nPara )
1035 nEndPos = rEditEngine.GetTextLen( nPara );
1038 // get list of char attribs
1039 rEditEngine.GetCharAttribs( nPara, aAttribs );
1041 bool bEmpty = true; // we found no item inside the selection of this paragraph
1042 bool bGaps = false; // we found items but there are gaps between them
1043 sal_Int32 nLastEnd = nPos;
1045 const SfxPoolItem* pParaItem = nullptr;
1047 for(const auto& rAttrib : aAttribs)
1049 OSL_ENSURE( rAttrib.pAttr, "GetCharAttribs gives corrupt data" );
1051 const bool bEmptyPortion = (rAttrib.nStart == rAttrib.nEnd);
1052 if( (!bEmptyPortion && (rAttrib.nStart >= nEndPos)) || (bEmptyPortion && (rAttrib.nStart > nEndPos)) )
1053 break; // break if we are already behind our selection
1055 if( (!bEmptyPortion && (rAttrib.nEnd <= nPos)) || (bEmptyPortion && (rAttrib.nEnd < nPos)) )
1056 continue; // or if the attribute ends before our selection
1058 if( rAttrib.pAttr->Which() != nWhich )
1059 continue; // skip if is not the searched item
1061 // if we already found an item
1062 if( pParaItem )
1064 // ... and its different to this one than the state is don't care
1065 if( *pParaItem != *(rAttrib.pAttr) )
1066 return SfxItemState::DONTCARE;
1068 else
1070 pParaItem = rAttrib.pAttr;
1073 if( bEmpty )
1074 bEmpty = false;
1076 if( !bGaps && rAttrib.nStart > nLastEnd )
1077 bGaps = true;
1079 nLastEnd = rAttrib.nEnd;
1082 if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
1083 bGaps = true;
1084 if( bEmpty )
1085 eParaState = SfxItemState::DEFAULT;
1086 else if( bGaps )
1087 eParaState = SfxItemState::DONTCARE;
1088 else
1089 eParaState = SfxItemState::SET;
1091 // if we already found an item check if we found the same
1092 if( pLastItem )
1094 if( (pParaItem == nullptr) || (*pLastItem != *pParaItem) )
1095 return SfxItemState::DONTCARE;
1097 else
1099 pLastItem = pParaItem;
1100 eState = eParaState;
1104 return eState;
1107 SfxItemState SmTextForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
1109 SfxItemState nState = SfxItemState::DISABLED;
1110 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1111 if (pEditEngine)
1112 nState = GetSvxEditEngineItemState( *pEditEngine, rSel, nWhich );
1113 return nState;
1116 SfxItemState SmTextForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
1118 SfxItemState nState = SfxItemState::DISABLED;
1119 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1120 if (pEditEngine)
1122 const SfxItemSet& rSet = pEditEngine->GetParaAttribs( nPara );
1123 nState = rSet.GetItemState( nWhich );
1125 return nState;
1128 LanguageType SmTextForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
1130 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1131 return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex) : LANGUAGE_NONE;
1134 sal_Int32 SmTextForwarder::GetFieldCount( sal_Int32 nPara ) const
1136 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1137 return pEditEngine ? pEditEngine->GetFieldCount(nPara) : 0;
1140 EFieldInfo SmTextForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
1142 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1143 return pEditEngine ? pEditEngine->GetFieldInfo( nPara, nField ) : EFieldInfo();
1146 EBulletInfo SmTextForwarder::GetBulletInfo( sal_Int32 /*nPara*/ ) const
1148 return EBulletInfo();
1151 tools::Rectangle SmTextForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
1153 tools::Rectangle aRect(0,0,0,0);
1154 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1156 if (pEditEngine)
1158 // Handle virtual position one-past-the end of the string
1159 if( nIndex >= pEditEngine->GetTextLen(nPara) )
1161 if( nIndex )
1162 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex-1) );
1164 aRect.Move( aRect.Right() - aRect.Left(), 0 );
1165 aRect.SetSize( Size(1, pEditEngine->GetTextHeight()) );
1167 else
1169 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex) );
1172 return aRect;
1175 tools::Rectangle SmTextForwarder::GetParaBounds( sal_Int32 nPara ) const
1177 tools::Rectangle aRect(0,0,0,0);
1178 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1180 if (pEditEngine)
1182 const Point aPnt = pEditEngine->GetDocPosTopLeft( nPara );
1183 const sal_uLong nWidth = pEditEngine->CalcTextWidth();
1184 const sal_uLong nHeight = pEditEngine->GetTextHeight( nPara );
1185 aRect = tools::Rectangle( aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight );
1188 return aRect;
1191 MapMode SmTextForwarder::GetMapMode() const
1193 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1194 return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode( MapUnit::Map100thMM );
1197 OutputDevice* SmTextForwarder::GetRefDevice() const
1199 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1200 return pEditEngine ? pEditEngine->GetRefDevice() : nullptr;
1203 bool SmTextForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
1205 bool bRes = false;
1206 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1207 if (pEditEngine)
1209 EPosition aDocPos = pEditEngine->FindDocPosition( rPos );
1210 nPara = aDocPos.nPara;
1211 nIndex = aDocPos.nIndex;
1212 bRes = true;
1214 return bRes;
1217 bool SmTextForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
1219 bool bRes = false;
1220 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1221 if (pEditEngine)
1223 ESelection aRes = pEditEngine->GetWord( ESelection(nPara, nIndex, nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD );
1225 if( aRes.nStartPara == nPara &&
1226 aRes.nStartPara == aRes.nEndPara )
1228 nStart = aRes.nStartPos;
1229 nEnd = aRes.nEndPos;
1231 bRes = true;
1235 return bRes;
1238 bool SmTextForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
1240 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1241 if (!pEditEngine)
1242 return false;
1243 SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex, bInCell );
1244 return true;
1247 sal_Int32 SmTextForwarder::GetLineCount( sal_Int32 nPara ) const
1249 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1250 return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
1253 sal_Int32 SmTextForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
1255 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1256 return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
1259 void SmTextForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
1261 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1262 if (pEditEngine)
1263 pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
1264 else
1265 rStart = rEnd = 0;
1268 sal_Int32 SmTextForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
1270 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1271 return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
1274 bool SmTextForwarder::QuickFormatDoc( bool /*bFull*/ )
1276 bool bRes = false;
1277 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1278 if (pEditEngine)
1280 pEditEngine->QuickFormatDoc();
1281 bRes = true;
1283 return bRes;
1286 sal_Int16 SmTextForwarder::GetDepth( sal_Int32 /*nPara*/ ) const
1288 // math has no outliner...
1289 return -1;
1292 bool SmTextForwarder::SetDepth( sal_Int32 /*nPara*/, sal_Int16 nNewDepth )
1294 // math has no outliner...
1295 return -1 == nNewDepth; // is it the value from 'GetDepth' ?
1298 bool SmTextForwarder::Delete( const ESelection& rSelection )
1300 bool bRes = false;
1301 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1302 if (pEditEngine)
1304 pEditEngine->QuickDelete( rSelection );
1305 pEditEngine->QuickFormatDoc();
1306 bRes = true;
1308 return bRes;
1311 bool SmTextForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
1313 bool bRes = false;
1314 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1315 if (pEditEngine)
1317 pEditEngine->QuickInsertText( rStr, rSelection );
1318 pEditEngine->QuickFormatDoc();
1319 bRes = true;
1321 return bRes;
1324 const SfxItemSet* SmTextForwarder::GetEmptyItemSetPtr()
1326 const SfxItemSet *pItemSet = nullptr;
1327 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1328 if (pEditEngine)
1330 pItemSet = &pEditEngine->GetEmptyItemSet();
1332 return pItemSet;
1335 void SmTextForwarder::AppendParagraph()
1337 // append an empty paragraph
1338 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1339 if (pEditEngine)
1341 sal_Int32 nParaCount = pEditEngine->GetParagraphCount();
1342 pEditEngine->InsertParagraph( nParaCount, OUString() );
1346 sal_Int32 SmTextForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet &rSet )
1348 sal_uInt16 nRes = 0;
1349 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1350 if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
1352 // append text
1353 ESelection aSel( nPara, pEditEngine->GetTextLen( nPara ) );
1354 pEditEngine->QuickInsertText( rText, aSel );
1356 // set attributes for new appended text
1357 nRes = aSel.nEndPos = pEditEngine->GetTextLen( nPara );
1358 pEditEngine->QuickSetAttribs( rSet, aSel );
1360 return nRes;
1363 void SmTextForwarder::CopyText(const SvxTextForwarder& rSource)
1366 const SmTextForwarder* pSourceForwarder = dynamic_cast< const SmTextForwarder* >( &rSource );
1367 if( !pSourceForwarder )
1368 return;
1369 EditEngine* pSourceEditEngine = pSourceForwarder->rEditAcc.GetEditEngine();
1370 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1371 if (pEditEngine && pSourceEditEngine )
1373 std::unique_ptr<EditTextObject> pNewTextObject = pSourceEditEngine->CreateTextObject();
1374 pEditEngine->SetText( *pNewTextObject );
1379 SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible& rAcc ) :
1380 rEditAcc( rAcc )
1384 SmEditViewForwarder::~SmEditViewForwarder()
1388 bool SmEditViewForwarder::IsValid() const
1390 return rEditAcc.GetEditView() != nullptr;
1394 Point SmEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1396 EditView *pEditView = rEditAcc.GetEditView();
1397 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
1399 if( pOutDev )
1401 MapMode aMapMode(pOutDev->GetMapMode());
1402 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
1403 MapMode(aMapMode.GetMapUnit())));
1404 aMapMode.SetOrigin(Point());
1405 return pOutDev->LogicToPixel( aPoint, aMapMode );
1408 return Point();
1411 Point SmEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1413 EditView *pEditView = rEditAcc.GetEditView();
1414 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
1416 if( pOutDev )
1418 MapMode aMapMode(pOutDev->GetMapMode());
1419 aMapMode.SetOrigin(Point());
1420 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
1421 return OutputDevice::LogicToLogic( aPoint,
1422 MapMode(aMapMode.GetMapUnit()),
1423 rMapMode );
1426 return Point();
1429 bool SmEditViewForwarder::GetSelection( ESelection& rSelection ) const
1431 bool bRes = false;
1432 EditView *pEditView = rEditAcc.GetEditView();
1433 if (pEditView)
1435 rSelection = pEditView->GetSelection();
1436 bRes = true;
1438 return bRes;
1441 bool SmEditViewForwarder::SetSelection( const ESelection& rSelection )
1443 bool bRes = false;
1444 EditView *pEditView = rEditAcc.GetEditView();
1445 if (pEditView)
1447 pEditView->SetSelection( rSelection );
1448 bRes = true;
1450 return bRes;
1453 bool SmEditViewForwarder::Copy()
1455 bool bRes = false;
1456 EditView *pEditView = rEditAcc.GetEditView();
1457 if (pEditView)
1459 pEditView->Copy();
1460 bRes = true;
1462 return bRes;
1465 bool SmEditViewForwarder::Cut()
1467 bool bRes = false;
1468 EditView *pEditView = rEditAcc.GetEditView();
1469 if (pEditView)
1471 pEditView->Cut();
1472 bRes = true;
1474 return bRes;
1477 bool SmEditViewForwarder::Paste()
1479 bool bRes = false;
1480 EditView *pEditView = rEditAcc.GetEditView();
1481 if (pEditView)
1483 pEditView->Paste();
1484 bRes = true;
1486 return bRes;
1490 SmEditAccessible::SmEditAccessible( SmEditWindow *pEditWin ) :
1491 aAccName (SmResId(STR_CMDBOXWINDOW)),
1492 pTextHelper (),
1493 pWin (pEditWin)
1495 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1498 SmEditAccessible::~SmEditAccessible()
1502 ::accessibility::AccessibleTextHelper *SmEditAccessible::GetTextHelper()
1504 return pTextHelper.get();
1507 void SmEditAccessible::Init()
1509 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1510 if (pWin)
1512 EditEngine *pEditEngine = pWin->GetEditEngine();
1513 EditView *pEditView = pWin->GetEditView();
1514 if (pEditEngine && pEditView)
1516 assert(!pTextHelper);
1517 pTextHelper.reset(new ::accessibility::AccessibleTextHelper( std::make_unique<SmEditSource>( *this ) ));
1518 pTextHelper->SetEventSource( this );
1523 void SmEditAccessible::ClearWin()
1525 // remove handler before current object gets destroyed
1526 // (avoid handler being called for already dead object)
1527 EditEngine *pEditEngine = GetEditEngine();
1528 if (pEditEngine)
1529 pEditEngine->SetNotifyHdl( Link<EENotify&,void>() );
1531 pWin = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
1533 //! make TextHelper implicitly release C++ references to some core objects
1534 pTextHelper->SetEditSource( ::std::unique_ptr<SvxEditSource>() );
1535 //! make TextHelper release references
1536 //! (e.g. the one set by the 'SetEventSource' call)
1537 pTextHelper->Dispose();
1538 pTextHelper.reset();
1541 // XAccessible
1542 uno::Reference< XAccessibleContext > SAL_CALL SmEditAccessible::getAccessibleContext( )
1544 return this;
1547 // XAccessibleComponent
1548 sal_Bool SAL_CALL SmEditAccessible::containsPoint( const awt::Point& aPoint )
1550 //! the arguments coordinates are relative to the current window !
1551 //! Thus the top left-point is (0, 0)
1553 SolarMutexGuard aGuard;
1554 if (!pWin)
1555 throw RuntimeException();
1557 Size aSz( pWin->GetSizePixel() );
1558 return aPoint.X >= 0 && aPoint.Y >= 0 &&
1559 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
1562 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleAtPoint( const awt::Point& aPoint )
1564 SolarMutexGuard aGuard;
1565 if (!pTextHelper)
1566 throw RuntimeException();
1567 return pTextHelper->GetAt( aPoint );
1570 awt::Rectangle SAL_CALL SmEditAccessible::getBounds( )
1572 SolarMutexGuard aGuard;
1573 if (!pWin)
1574 throw RuntimeException();
1575 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1576 "mismatch of window parent and accessible parent" );
1577 return lcl_GetBounds( pWin );
1580 awt::Point SAL_CALL SmEditAccessible::getLocation( )
1582 SolarMutexGuard aGuard;
1583 if (!pWin)
1584 throw RuntimeException();
1585 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1586 "mismatch of window parent and accessible parent" );
1587 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1588 return awt::Point( aRect.X, aRect.Y );
1591 awt::Point SAL_CALL SmEditAccessible::getLocationOnScreen( )
1593 SolarMutexGuard aGuard;
1594 if (!pWin)
1595 throw RuntimeException();
1596 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1597 "mismatch of window parent and accessible parent" );
1598 return lcl_GetLocationOnScreen( pWin );
1601 awt::Size SAL_CALL SmEditAccessible::getSize( )
1603 SolarMutexGuard aGuard;
1604 if (!pWin)
1605 throw RuntimeException();
1606 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1607 "mismatch of window parent and accessible parent" );
1609 Size aSz( pWin->GetSizePixel() );
1610 #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1611 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1612 Size aSz2( aRect.Width, aRect.Height );
1613 assert(aSz == aSz2 && "mismatch in width");
1614 #endif
1615 return awt::Size( aSz.Width(), aSz.Height() );
1618 void SAL_CALL SmEditAccessible::grabFocus( )
1620 SolarMutexGuard aGuard;
1621 if (!pWin)
1622 throw RuntimeException();
1624 pWin->GrabFocus();
1627 sal_Int32 SAL_CALL SmEditAccessible::getForeground()
1629 SolarMutexGuard aGuard;
1631 if (!pWin)
1632 throw RuntimeException();
1633 return static_cast<sal_Int32>(pWin->GetTextColor());
1636 sal_Int32 SAL_CALL SmEditAccessible::getBackground()
1638 SolarMutexGuard aGuard;
1640 if (!pWin)
1641 throw RuntimeException();
1642 Wallpaper aWall( pWin->GetDisplayBackground() );
1643 Color nCol;
1644 if (aWall.IsBitmap() || aWall.IsGradient())
1645 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor();
1646 else
1647 nCol = aWall.GetColor();
1648 return static_cast<sal_Int32>(nCol);
1651 // XAccessibleContext
1652 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleChildCount( )
1654 SolarMutexGuard aGuard;
1655 if (!pTextHelper)
1656 return 0;
1657 return pTextHelper->GetChildCount();
1660 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleChild( sal_Int32 i )
1662 SolarMutexGuard aGuard;
1663 if (!pTextHelper)
1664 throw RuntimeException();
1665 return pTextHelper->GetChild( i );
1668 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleParent( )
1670 SolarMutexGuard aGuard;
1671 if (!pWin)
1672 throw RuntimeException();
1674 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
1675 OSL_ENSURE( pAccParent, "accessible parent missing" );
1676 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
1679 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleIndexInParent( )
1681 SolarMutexGuard aGuard;
1682 sal_Int32 nIdx = -1;
1683 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : nullptr;
1684 if (pAccParent)
1686 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
1687 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
1688 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
1689 nIdx = i;
1691 return nIdx;
1694 sal_Int16 SAL_CALL SmEditAccessible::getAccessibleRole( )
1696 return AccessibleRole::TEXT_FRAME;
1699 OUString SAL_CALL SmEditAccessible::getAccessibleDescription( )
1701 return OUString(); // empty as agreed with product-management
1704 OUString SAL_CALL SmEditAccessible::getAccessibleName( )
1706 SolarMutexGuard aGuard;
1707 // same name as displayed by the window when not docked
1708 return aAccName;
1711 uno::Reference< XAccessibleRelationSet > SAL_CALL SmEditAccessible::getAccessibleRelationSet( )
1713 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
1714 return xRelSet; // empty relation set
1717 uno::Reference< XAccessibleStateSet > SAL_CALL SmEditAccessible::getAccessibleStateSet( )
1719 SolarMutexGuard aGuard;
1720 ::utl::AccessibleStateSetHelper *pStateSet =
1721 new ::utl::AccessibleStateSetHelper;
1723 Reference<XAccessibleStateSet> xStateSet( pStateSet );
1725 if (!pWin || !pTextHelper)
1726 pStateSet->AddState( AccessibleStateType::DEFUNC );
1727 else
1729 pStateSet->AddState( AccessibleStateType::MULTI_LINE );
1730 pStateSet->AddState( AccessibleStateType::ENABLED );
1731 pStateSet->AddState( AccessibleStateType::EDITABLE );
1732 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
1733 if (pWin->HasFocus())
1734 pStateSet->AddState( AccessibleStateType::FOCUSED );
1735 if (pWin->IsActive())
1736 pStateSet->AddState( AccessibleStateType::ACTIVE );
1737 if (pWin->IsVisible())
1738 pStateSet->AddState( AccessibleStateType::SHOWING );
1739 if (pWin->IsReallyVisible())
1740 pStateSet->AddState( AccessibleStateType::VISIBLE );
1741 if (COL_TRANSPARENT != pWin->GetBackground().GetColor())
1742 pStateSet->AddState( AccessibleStateType::OPAQUE );
1745 return xStateSet;
1748 Locale SAL_CALL SmEditAccessible::getLocale( )
1750 SolarMutexGuard aGuard;
1751 // should be the document language...
1752 // We use the language of the localized symbol names here.
1753 return Application::GetSettings().GetUILanguageTag().getLocale();
1757 // XAccessibleEventBroadcaster
1758 void SAL_CALL SmEditAccessible::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1760 if (pTextHelper) // not disposing (about to destroy view shell)
1761 pTextHelper->AddEventListener( xListener );
1764 void SAL_CALL SmEditAccessible::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1766 if (pTextHelper) // not disposing (about to destroy view shell)
1767 pTextHelper->RemoveEventListener( xListener );
1770 OUString SAL_CALL SmEditAccessible::getImplementationName()
1772 return "SmEditAccessible";
1775 sal_Bool SAL_CALL SmEditAccessible::supportsService(
1776 const OUString& rServiceName )
1778 return cppu::supportsService(this, rServiceName);
1781 Sequence< OUString > SAL_CALL SmEditAccessible::getSupportedServiceNames()
1783 return {
1784 "css::accessibility::Accessible",
1785 "css::accessibility::AccessibleComponent",
1786 "css::accessibility::AccessibleContext"
1791 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */