cURL: follow redirects
[LibreOffice.git] / starmath / source / accessibility.cxx
blob19cc51784a620bfccf484f40721afec36b379799
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>
22 #include <memory>
23 #include <utility>
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/XAccessibleEventListener.hpp>
29 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
30 #include <com/sun/star/awt/FocusEvent.hpp>
31 #include <com/sun/star/awt/XFocusListener.hpp>
32 #include <unotools/accessiblerelationsethelper.hxx>
34 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
35 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
36 #include <com/sun/star/i18n/WordType.hpp>
37 #include <unotools/accessiblestatesethelper.hxx>
38 #include <comphelper/accessibleeventnotifier.hxx>
39 #include <cppuhelper/supportsservice.hxx>
40 #include <osl/diagnose.h>
41 #include <vcl/svapp.hxx>
42 #include <vcl/window.hxx>
43 #include <vcl/unohelp2.hxx>
44 #include <vcl/settings.hxx>
46 #include <tools/gen.hxx>
47 #include <osl/mutex.hxx>
48 #include <svl/itemset.hxx>
50 #include <editeng/editobj.hxx>
51 #include <editeng/editdata.hxx>
52 #include <editeng/editview.hxx>
53 #include <editeng/eeitem.hxx>
54 #include <editeng/outliner.hxx>
55 #include <editeng/unoedhlp.hxx>
58 #include "accessibility.hxx"
59 #include <unomodel.hxx>
60 #include <document.hxx>
61 #include <view.hxx>
62 #include <o3tl/make_unique.hxx>
63 using namespace com::sun::star;
64 using namespace com::sun::star::lang;
65 using namespace com::sun::star::uno;
66 using namespace com::sun::star::accessibility;
69 static awt::Rectangle lcl_GetBounds( vcl::Window *pWin )
71 // !! see VCLXAccessibleComponent::implGetBounds()
73 //! the coordinates returned are relativ to the parent window !
74 //! Thus the top-left point may be different from (0, 0) !
76 awt::Rectangle aBounds;
77 if (pWin)
79 Rectangle aRect = pWin->GetWindowExtentsRelative( nullptr );
80 aBounds.X = aRect.Left();
81 aBounds.Y = aRect.Top();
82 aBounds.Width = aRect.GetWidth();
83 aBounds.Height = aRect.GetHeight();
84 vcl::Window* pParent = pWin->GetAccessibleParentWindow();
85 if (pParent)
87 Rectangle aParentRect = pParent->GetWindowExtentsRelative( nullptr );
88 awt::Point aParentScreenLoc( aParentRect.Left(), aParentRect.Top() );
89 aBounds.X -= aParentScreenLoc.X;
90 aBounds.Y -= aParentScreenLoc.Y;
93 return aBounds;
96 static awt::Point lcl_GetLocationOnScreen( vcl::Window *pWin )
98 // !! see VCLXAccessibleComponent::getLocationOnScreen()
100 awt::Point aPos;
101 if (pWin)
103 Rectangle aRect = pWin->GetWindowExtentsRelative( nullptr );
104 aPos.X = aRect.Left();
105 aPos.Y = aRect.Top();
107 return aPos;
111 SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow *pGraphicWin ) :
112 aAccName (SM_RESSTR(RID_DOCUMENTSTR)),
113 nClientId (0),
114 pWin (pGraphicWin)
116 OSL_ENSURE( pWin, "SmGraphicAccessible: window missing" );
119 SmGraphicAccessible::~SmGraphicAccessible()
124 SmDocShell * SmGraphicAccessible::GetDoc_Impl()
126 SmViewShell *pView = pWin ? pWin->GetView() : nullptr;
127 return pView ? pView->GetDoc() : nullptr;
130 OUString SmGraphicAccessible::GetAccessibleText_Impl()
132 OUString aTxt;
133 SmDocShell *pDoc = GetDoc_Impl();
134 if (pDoc)
135 aTxt = pDoc->GetAccessibleText();
136 return aTxt;
139 void SmGraphicAccessible::ClearWin()
141 pWin = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
143 if ( nClientId )
145 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
146 nClientId = 0;
150 void SmGraphicAccessible::LaunchEvent(
151 const sal_Int16 nAccesibleEventId,
152 const uno::Any &rOldVal,
153 const uno::Any &rNewVal)
155 AccessibleEventObject aEvt;
156 aEvt.Source = static_cast<XAccessible *>(this);
157 aEvt.EventId = nAccesibleEventId;
158 aEvt.OldValue = rOldVal;
159 aEvt.NewValue = rNewVal ;
161 // pass event on to event-listener's
162 if (nClientId)
163 comphelper::AccessibleEventNotifier::addEvent( nClientId, aEvt );
166 uno::Reference< XAccessibleContext > SAL_CALL SmGraphicAccessible::getAccessibleContext()
167 throw (RuntimeException, std::exception)
169 SolarMutexGuard aGuard;
170 return this;
173 sal_Bool SAL_CALL SmGraphicAccessible::containsPoint( const awt::Point& aPoint )
174 throw (RuntimeException, std::exception)
176 //! the arguments coordinates are relativ to the current window !
177 //! Thus the top-left point is (0, 0)
179 SolarMutexGuard aGuard;
180 if (!pWin)
181 throw RuntimeException();
183 Size aSz( pWin->GetSizePixel() );
184 return aPoint.X >= 0 && aPoint.Y >= 0 &&
185 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
188 uno::Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleAtPoint(
189 const awt::Point& aPoint )
190 throw (RuntimeException, std::exception)
192 SolarMutexGuard aGuard;
193 XAccessible *pRes = nullptr;
194 if (containsPoint( aPoint ))
195 pRes = this;
196 return pRes;
199 awt::Rectangle SAL_CALL SmGraphicAccessible::getBounds()
200 throw (RuntimeException, std::exception)
202 SolarMutexGuard aGuard;
203 if (!pWin)
204 throw RuntimeException();
205 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
206 "mismatch of window parent and accessible parent" );
207 return lcl_GetBounds( pWin );
210 awt::Point SAL_CALL SmGraphicAccessible::getLocation()
211 throw (RuntimeException, std::exception)
213 SolarMutexGuard aGuard;
214 if (!pWin)
215 throw RuntimeException();
216 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
217 "mismatch of window parent and accessible parent" );
218 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
219 return awt::Point( aRect.X, aRect.Y );
222 awt::Point SAL_CALL SmGraphicAccessible::getLocationOnScreen()
223 throw (RuntimeException, std::exception)
225 SolarMutexGuard aGuard;
226 if (!pWin)
227 throw RuntimeException();
228 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
229 "mismatch of window parent and accessible parent" );
230 return lcl_GetLocationOnScreen( pWin );
233 awt::Size SAL_CALL SmGraphicAccessible::getSize()
234 throw (RuntimeException, std::exception)
236 SolarMutexGuard aGuard;
237 if (!pWin)
238 throw RuntimeException();
239 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
240 "mismatch of window parent and accessible parent" );
242 Size aSz( pWin->GetSizePixel() );
243 #if OSL_DEBUG_LEVEL > 0
244 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
245 Size aSz2( aRect.Width, aRect.Height );
246 assert(aSz == aSz2 && "mismatch in width" );
247 #endif
248 return awt::Size( aSz.Width(), aSz.Height() );
251 void SAL_CALL SmGraphicAccessible::grabFocus()
252 throw (RuntimeException, std::exception)
254 SolarMutexGuard aGuard;
255 if (!pWin)
256 throw RuntimeException();
258 pWin->GrabFocus();
261 sal_Int32 SAL_CALL SmGraphicAccessible::getForeground()
262 throw (RuntimeException, std::exception)
264 SolarMutexGuard aGuard;
266 if (!pWin)
267 throw RuntimeException();
268 return static_cast<sal_Int32>(pWin->GetTextColor().GetColor());
271 sal_Int32 SAL_CALL SmGraphicAccessible::getBackground()
272 throw (RuntimeException, std::exception)
274 SolarMutexGuard aGuard;
276 if (!pWin)
277 throw RuntimeException();
278 Wallpaper aWall( pWin->GetDisplayBackground() );
279 ColorData nCol;
280 if (aWall.IsBitmap() || aWall.IsGradient())
281 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
282 else
283 nCol = aWall.GetColor().GetColor();
284 return static_cast<sal_Int32>(nCol);
287 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleChildCount()
288 throw (RuntimeException, std::exception)
290 SolarMutexGuard aGuard;
291 return 0;
294 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleChild(
295 sal_Int32 /*i*/ )
296 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
298 SolarMutexGuard aGuard;
299 throw IndexOutOfBoundsException(); // there is no child...
302 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleParent()
303 throw (RuntimeException, std::exception)
305 SolarMutexGuard aGuard;
306 if (!pWin)
307 throw RuntimeException();
309 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
310 OSL_ENSURE( pAccParent, "accessible parent missing" );
311 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
314 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleIndexInParent()
315 throw (RuntimeException, std::exception)
317 SolarMutexGuard aGuard;
318 sal_Int32 nIdx = -1;
319 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : nullptr;
320 if (pAccParent)
322 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
323 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
324 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
325 nIdx = i;
327 return nIdx;
330 sal_Int16 SAL_CALL SmGraphicAccessible::getAccessibleRole()
331 throw (RuntimeException, std::exception)
333 SolarMutexGuard aGuard;
334 return AccessibleRole::DOCUMENT;
337 OUString SAL_CALL SmGraphicAccessible::getAccessibleDescription()
338 throw (RuntimeException, std::exception)
340 SolarMutexGuard aGuard;
341 SmDocShell *pDoc = GetDoc_Impl();
342 return pDoc ? OUString(pDoc->GetText()) : OUString();
345 OUString SAL_CALL SmGraphicAccessible::getAccessibleName()
346 throw (RuntimeException, std::exception)
348 SolarMutexGuard aGuard;
349 return aAccName;
352 Reference< XAccessibleRelationSet > SAL_CALL SmGraphicAccessible::getAccessibleRelationSet()
353 throw (RuntimeException, std::exception)
355 SolarMutexGuard aGuard;
356 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
357 return xRelSet; // empty relation set
360 Reference< XAccessibleStateSet > SAL_CALL SmGraphicAccessible::getAccessibleStateSet()
361 throw (RuntimeException, std::exception)
363 SolarMutexGuard aGuard;
364 ::utl::AccessibleStateSetHelper *pStateSet =
365 new ::utl::AccessibleStateSetHelper;
367 Reference<XAccessibleStateSet> xStateSet( pStateSet );
369 if (!pWin)
370 pStateSet->AddState( AccessibleStateType::DEFUNC );
371 else
373 pStateSet->AddState( AccessibleStateType::ENABLED );
374 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
375 if (pWin->HasFocus())
376 pStateSet->AddState( AccessibleStateType::FOCUSED );
377 if (pWin->IsActive())
378 pStateSet->AddState( AccessibleStateType::ACTIVE );
379 if (pWin->IsVisible())
380 pStateSet->AddState( AccessibleStateType::SHOWING );
381 if (pWin->IsReallyVisible())
382 pStateSet->AddState( AccessibleStateType::VISIBLE );
383 if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
384 pStateSet->AddState( AccessibleStateType::OPAQUE );
387 return xStateSet;
390 Locale SAL_CALL SmGraphicAccessible::getLocale()
391 throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
393 SolarMutexGuard aGuard;
394 // should be the document language...
395 // We use the language of the localized symbol names here.
396 return Application::GetSettings().GetUILanguageTag().getLocale();
400 void SAL_CALL SmGraphicAccessible::addAccessibleEventListener(
401 const Reference< XAccessibleEventListener >& xListener )
402 throw (RuntimeException, std::exception)
404 if (xListener.is())
406 SolarMutexGuard aGuard;
407 if (pWin)
409 if (!nClientId)
410 nClientId = comphelper::AccessibleEventNotifier::registerClient( );
411 comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
416 void SAL_CALL SmGraphicAccessible::removeAccessibleEventListener(
417 const Reference< XAccessibleEventListener >& xListener )
418 throw (RuntimeException, std::exception)
420 if (xListener.is() && nClientId)
422 SolarMutexGuard aGuard;
423 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener );
424 if ( !nListenerCount )
426 // no listeners anymore
427 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
428 // and at least to us not firing any events anymore, in case somebody calls
429 // NotifyAccessibleEvent, again
430 comphelper::AccessibleEventNotifier::revokeClient( nClientId );
431 nClientId = 0;
436 sal_Int32 SAL_CALL SmGraphicAccessible::getCaretPosition()
437 throw (RuntimeException, std::exception)
439 SolarMutexGuard aGuard;
440 return 0;
443 sal_Bool SAL_CALL SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex )
444 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
446 SolarMutexGuard aGuard;
447 OUString aTxt( GetAccessibleText_Impl() );
448 if (!(nIndex < aTxt.getLength()))
449 throw IndexOutOfBoundsException();
450 return false;
453 sal_Unicode SAL_CALL SmGraphicAccessible::getCharacter( sal_Int32 nIndex )
454 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
456 SolarMutexGuard aGuard;
457 OUString aTxt( GetAccessibleText_Impl() );
458 if (!(nIndex < aTxt.getLength()))
459 throw IndexOutOfBoundsException();
460 return aTxt[nIndex];
463 Sequence< beans::PropertyValue > SAL_CALL SmGraphicAccessible::getCharacterAttributes(
464 sal_Int32 nIndex,
465 const uno::Sequence< OUString > & /*rRequestedAttributes*/ )
466 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
468 SolarMutexGuard aGuard;
469 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
470 if (!(0 <= nIndex && nIndex < nLen))
471 throw IndexOutOfBoundsException();
472 return Sequence< beans::PropertyValue >();
475 awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex )
476 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
478 SolarMutexGuard aGuard;
480 awt::Rectangle aRes;
482 if (!pWin)
483 throw RuntimeException();
484 else
486 // get accessible text
487 SmViewShell *pView = pWin->GetView();
488 SmDocShell *pDoc = pView ? pView->GetDoc() : nullptr;
489 if (!pDoc)
490 throw RuntimeException();
491 OUString aTxt( GetAccessibleText_Impl() );
492 if (!(0 <= nIndex && nIndex <= aTxt.getLength())) // aTxt.getLength() is valid
493 throw IndexOutOfBoundsException();
495 // find a reasonable rectangle for position aTxt.getLength().
496 bool bWasBehindText = (nIndex == aTxt.getLength());
497 if (bWasBehindText && nIndex)
498 --nIndex;
500 const SmNode *pTree = pDoc->GetFormulaTree();
501 const SmNode *pNode = pTree->FindNodeWithAccessibleIndex( nIndex );
502 //! pNode may be 0 if the index belongs to a char that was inserted
503 //! only for the accessible text!
504 if (pNode)
506 sal_Int32 nAccIndex = pNode->GetAccessibleIndex();
507 OSL_ENSURE( nAccIndex >= 0, "invalid accessible index" );
508 OSL_ENSURE( nIndex >= nAccIndex, "index out of range" );
510 OUStringBuffer aBuf;
511 pNode->GetAccessibleText(aBuf);
512 OUString aNodeText = aBuf.makeStringAndClear();
513 sal_Int32 nNodeIndex = nIndex - nAccIndex;
514 if (0 <= nNodeIndex && nNodeIndex < aNodeText.getLength())
516 // get appropriate rectangle
517 Point aOffset(pNode->GetTopLeft() - pTree->GetTopLeft());
518 Point aTLPos (pWin->GetFormulaDrawPos() + aOffset);
519 aTLPos.X() -= 0;
520 Size aSize (pNode->GetSize());
522 long* pXAry = new long[ aNodeText.getLength() ];
523 pWin->SetFont( pNode->GetFont() );
524 pWin->GetTextArray( aNodeText, pXAry, 0, aNodeText.getLength() );
525 aTLPos.X() += nNodeIndex > 0 ? pXAry[nNodeIndex - 1] : 0;
526 aSize.Width() = nNodeIndex > 0 ? pXAry[nNodeIndex] - pXAry[nNodeIndex - 1] : pXAry[nNodeIndex];
527 delete[] pXAry;
529 aTLPos = pWin->LogicToPixel( aTLPos );
530 aSize = pWin->LogicToPixel( aSize );
531 aRes.X = aTLPos.X();
532 aRes.Y = aTLPos.Y();
533 aRes.Width = aSize.Width();
534 aRes.Height = aSize.Height();
538 // take rectangle from last character and move it to the right
539 if (bWasBehindText)
540 aRes.X += aRes.Width;
543 return aRes;
546 sal_Int32 SAL_CALL SmGraphicAccessible::getCharacterCount()
547 throw (RuntimeException, std::exception)
549 SolarMutexGuard aGuard;
550 return GetAccessibleText_Impl().getLength();
553 sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoint )
554 throw (RuntimeException, std::exception)
556 SolarMutexGuard aGuard;
558 sal_Int32 nRes = -1;
559 if (pWin)
561 const SmNode *pTree = pWin->GetView()->GetDoc()->GetFormulaTree();
562 // can be NULL! e.g. if one clicks within the window already during loading of the
563 // document (before the parser even started)
564 if (!pTree)
565 return nRes;
567 // get position relative to formula draw position
568 Point aPos( aPoint.X, aPoint.Y );
569 aPos = pWin->PixelToLogic( aPos );
570 aPos -= pWin->GetFormulaDrawPos();
572 // if it was inside the formula then get the appropriate node
573 const SmNode *pNode = nullptr;
574 if (pTree->OrientedDist(aPos) <= 0)
575 pNode = pTree->FindRectClosestTo(aPos);
577 if (pNode)
579 // get appropriate rectangle
580 Point aOffset( pNode->GetTopLeft() - pTree->GetTopLeft() );
581 Point aTLPos ( aOffset );
582 aTLPos.X() -= 0;
583 Size aSize( pNode->GetSize() );
585 Rectangle aRect( aTLPos, aSize );
586 if (aRect.IsInside( aPos ))
588 OSL_ENSURE( pNode->IsVisible(), "node is not a leaf" );
589 OUStringBuffer aBuf;
590 pNode->GetAccessibleText(aBuf);
591 OUString aTxt = aBuf.makeStringAndClear();
592 OSL_ENSURE( !aTxt.isEmpty(), "no accessible text available" );
594 long nNodeX = pNode->GetLeft();
596 long* pXAry = new long[ aTxt.getLength() ];
597 pWin->SetFont( pNode->GetFont() );
598 pWin->GetTextArray( aTxt, pXAry, 0, aTxt.getLength() );
599 for (sal_Int32 i = 0; i < aTxt.getLength() && nRes == -1; ++i)
601 if (pXAry[i] + nNodeX > aPos.X())
602 nRes = i;
604 delete[] pXAry;
605 OSL_ENSURE( nRes >= 0 && nRes < aTxt.getLength(), "index out of range" );
606 OSL_ENSURE( pNode->GetAccessibleIndex() >= 0,
607 "invalid accessible index" );
609 nRes = pNode->GetAccessibleIndex() + nRes;
613 return nRes;
616 OUString SAL_CALL SmGraphicAccessible::getSelectedText()
617 throw (RuntimeException, std::exception)
619 SolarMutexGuard aGuard;
620 return OUString();
623 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionStart()
624 throw (RuntimeException, std::exception)
626 SolarMutexGuard aGuard;
627 return -1;
630 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionEnd()
631 throw (RuntimeException, std::exception)
633 SolarMutexGuard aGuard;
634 return -1;
637 sal_Bool SAL_CALL SmGraphicAccessible::setSelection(
638 sal_Int32 nStartIndex,
639 sal_Int32 nEndIndex )
640 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
642 SolarMutexGuard aGuard;
643 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
644 if (!(0 <= nStartIndex && nStartIndex < nLen) ||
645 !(0 <= nEndIndex && nEndIndex < nLen))
646 throw IndexOutOfBoundsException();
647 return false;
650 OUString SAL_CALL SmGraphicAccessible::getText()
651 throw (RuntimeException, std::exception)
653 SolarMutexGuard aGuard;
654 return GetAccessibleText_Impl();
657 OUString SAL_CALL SmGraphicAccessible::getTextRange(
658 sal_Int32 nStartIndex,
659 sal_Int32 nEndIndex )
660 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
662 //!! nEndIndex may be the string length per definition of the interface !!
663 //!! text should be copied exclusive that end index though. And arguments
664 //!! may be switched.
666 SolarMutexGuard aGuard;
667 OUString aTxt( GetAccessibleText_Impl() );
668 sal_Int32 nStart = std::min(nStartIndex, nEndIndex);
669 sal_Int32 nEnd = std::max(nStartIndex, nEndIndex);
670 if (!(nStart <= aTxt.getLength()) ||
671 !(nEnd <= aTxt.getLength()))
672 throw IndexOutOfBoundsException();
673 return aTxt.copy( nStart, nEnd - nStart );
676 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception)
678 SolarMutexGuard aGuard;
679 OUString aTxt( GetAccessibleText_Impl() );
680 //!! nIndex is allowed to be the string length
681 if (!(nIndex <= aTxt.getLength()))
682 throw IndexOutOfBoundsException();
684 css::accessibility::TextSegment aResult;
685 aResult.SegmentStart = -1;
686 aResult.SegmentEnd = -1;
687 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
689 aResult.SegmentText = aTxt.copy(nIndex, 1);
690 aResult.SegmentStart = nIndex;
691 aResult.SegmentEnd = nIndex+1;
693 return aResult;
696 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception)
698 SolarMutexGuard aGuard;
699 OUString aTxt( GetAccessibleText_Impl() );
700 //!! nIndex is allowed to be the string length
701 if (!(nIndex <= aTxt.getLength()))
702 throw IndexOutOfBoundsException();
704 css::accessibility::TextSegment aResult;
705 aResult.SegmentStart = -1;
706 aResult.SegmentEnd = -1;
708 if ( (AccessibleTextType::CHARACTER == aTextType) && nIndex )
710 aResult.SegmentText = aTxt.copy(nIndex-1, 1);
711 aResult.SegmentStart = nIndex-1;
712 aResult.SegmentEnd = nIndex;
714 return aResult;
717 css::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (css::lang::IndexOutOfBoundsException, css::lang::IllegalArgumentException, css::uno::RuntimeException, std::exception)
719 SolarMutexGuard aGuard;
720 OUString aTxt( GetAccessibleText_Impl() );
721 //!! nIndex is allowed to be the string length
722 if (!(nIndex <= aTxt.getLength()))
723 throw IndexOutOfBoundsException();
725 css::accessibility::TextSegment aResult;
726 aResult.SegmentStart = -1;
727 aResult.SegmentEnd = -1;
729 nIndex++; // text *behind*
730 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
732 aResult.SegmentText = aTxt.copy(nIndex, 1);
733 aResult.SegmentStart = nIndex;
734 aResult.SegmentEnd = nIndex+1;
736 return aResult;
739 sal_Bool SAL_CALL SmGraphicAccessible::copyText(
740 sal_Int32 nStartIndex,
741 sal_Int32 nEndIndex )
742 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
744 SolarMutexGuard aGuard;
745 bool bReturn = false;
747 if (!pWin)
748 throw RuntimeException();
749 else
751 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWin->GetClipboard();
752 if ( xClipboard.is() )
754 OUString sText( getTextRange(nStartIndex, nEndIndex) );
756 vcl::unohelper::TextDataObject* pDataObj = new vcl::unohelper::TextDataObject( sText );
757 SolarMutexReleaser aReleaser;
758 xClipboard->setContents( pDataObj, nullptr );
760 Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
761 if( xFlushableClipboard.is() )
762 xFlushableClipboard->flushClipboard();
764 bReturn = true;
768 return bReturn;
771 OUString SAL_CALL SmGraphicAccessible::getImplementationName()
772 throw (RuntimeException, std::exception)
774 return OUString("SmGraphicAccessible");
777 sal_Bool SAL_CALL SmGraphicAccessible::supportsService(
778 const OUString& rServiceName )
779 throw (RuntimeException, std::exception)
781 return cppu::supportsService(this, rServiceName);
784 Sequence< OUString > SAL_CALL SmGraphicAccessible::getSupportedServiceNames()
785 throw (RuntimeException, std::exception)
787 return Sequence< OUString >{
788 "css::accessibility::Accessible",
789 "css::accessibility::AccessibleComponent",
790 "css::accessibility::AccessibleContext",
791 "css::accessibility::AccessibleText"
796 SmEditSource::SmEditSource( SmEditWindow * /*pWin*/, SmEditAccessible &rAcc ) :
797 aViewFwd (rAcc),
798 aTextFwd (rAcc, *this),
799 aEditViewFwd(rAcc),
800 rEditAcc (rAcc)
804 SmEditSource::SmEditSource( const SmEditSource &rSrc ) :
805 SvxEditSource(),
806 aViewFwd (rSrc.rEditAcc),
807 aTextFwd (rSrc.rEditAcc, *this),
808 aEditViewFwd(rSrc.rEditAcc),
809 rEditAcc (rSrc.rEditAcc)
813 SmEditSource::~SmEditSource()
817 SvxEditSource* SmEditSource::Clone() const
819 return new SmEditSource( *this );
822 SvxTextForwarder* SmEditSource::GetTextForwarder()
824 return &aTextFwd;
827 SvxViewForwarder* SmEditSource::GetViewForwarder()
829 return &aViewFwd;
832 SvxEditViewForwarder* SmEditSource::GetEditViewForwarder( bool /*bCreate*/ )
834 return &aEditViewFwd;
837 void SmEditSource::UpdateData()
839 // would possibly only by needed if the XText interface is implemented
840 // and its text needs to be updated.
843 SfxBroadcaster & SmEditSource::GetBroadcaster() const
845 return const_cast<SmEditSource*>(this)->aBroadCaster;
848 SmViewForwarder::SmViewForwarder( SmEditAccessible &rAcc ) :
849 rEditAcc(rAcc)
853 SmViewForwarder::~SmViewForwarder()
857 bool SmViewForwarder::IsValid() const
859 return rEditAcc.GetEditView() != nullptr;
862 Rectangle SmViewForwarder::GetVisArea() const
864 EditView *pEditView = rEditAcc.GetEditView();
865 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
867 if( pOutDev && pEditView)
869 Rectangle aVisArea = pEditView->GetVisArea();
871 // figure out map mode from edit engine
872 EditEngine* pEditEngine = pEditView->GetEditEngine();
874 if( pEditEngine )
876 MapMode aMapMode(pOutDev->GetMapMode());
877 aVisArea = OutputDevice::LogicToLogic( aVisArea,
878 pEditEngine->GetRefMapMode(),
879 aMapMode.GetMapUnit() );
880 aMapMode.SetOrigin(Point());
881 return pOutDev->LogicToPixel( aVisArea, aMapMode );
885 return Rectangle();
888 Point SmViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
890 EditView *pEditView = rEditAcc.GetEditView();
891 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
893 if( pOutDev )
895 MapMode aMapMode(pOutDev->GetMapMode());
896 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
897 aMapMode.GetMapUnit() ) );
898 aMapMode.SetOrigin(Point());
899 return pOutDev->LogicToPixel( aPoint, aMapMode );
902 return Point();
905 Point SmViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
907 EditView *pEditView = rEditAcc.GetEditView();
908 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
910 if( pOutDev )
912 MapMode aMapMode(pOutDev->GetMapMode());
913 aMapMode.SetOrigin(Point());
914 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
915 return OutputDevice::LogicToLogic( aPoint,
916 aMapMode.GetMapUnit(),
917 rMapMode );
920 return Point();
924 SmTextForwarder::SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource) :
925 rEditAcc ( rAcc ),
926 rEditSource (rSource)
928 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
929 if (pEditEngine)
930 pEditEngine->SetNotifyHdl( LINK(this, SmTextForwarder, NotifyHdl) );
933 SmTextForwarder::~SmTextForwarder()
935 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
936 if (pEditEngine)
937 pEditEngine->SetNotifyHdl( Link<EENotify&,void>() );
940 IMPL_LINK(SmTextForwarder, NotifyHdl, EENotify&, rNotify, void)
942 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( &rNotify );
943 if (aHint.get())
944 rEditSource.GetBroadcaster().Broadcast( *aHint.get() );
947 sal_Int32 SmTextForwarder::GetParagraphCount() const
949 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
950 return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
953 sal_Int32 SmTextForwarder::GetTextLen( sal_Int32 nParagraph ) const
955 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
956 return pEditEngine ? pEditEngine->GetTextLen( nParagraph ) : 0;
959 OUString SmTextForwarder::GetText( const ESelection& rSel ) const
961 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
962 OUString aRet;
963 if (pEditEngine)
964 aRet = pEditEngine->GetText( rSel );
965 return convertLineEnd(aRet, GetSystemLineEnd());
968 SfxItemSet SmTextForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
970 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
971 assert(pEditEngine && "EditEngine missing");
972 if( rSel.nStartPara == rSel.nEndPara )
974 GetAttribsFlags nFlags = GetAttribsFlags::NONE;
975 switch( nOnlyHardAttrib )
977 case EditEngineAttribs_All:
978 nFlags = GetAttribsFlags::ALL;
979 break;
980 case EditEngineAttribs_HardAndPara:
981 nFlags = GetAttribsFlags::PARAATTRIBS|GetAttribsFlags::CHARATTRIBS;
982 break;
983 case EditEngineAttribs_OnlyHard:
984 nFlags = GetAttribsFlags::CHARATTRIBS;
985 break;
986 default:
987 SAL_WARN("starmath", "unknown flags for SmTextForwarder::GetAttribs");
990 return pEditEngine->GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
992 else
994 return pEditEngine->GetAttribs( rSel, nOnlyHardAttrib );
998 SfxItemSet SmTextForwarder::GetParaAttribs( sal_Int32 nPara ) const
1000 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1001 assert(pEditEngine && "EditEngine missing");
1003 SfxItemSet aSet( pEditEngine->GetParaAttribs( nPara ) );
1005 sal_uInt16 nWhich = EE_PARA_START;
1006 while( nWhich <= EE_PARA_END )
1008 if( aSet.GetItemState( nWhich ) != SfxItemState::SET )
1010 if( pEditEngine->HasParaAttrib( nPara, nWhich ) )
1011 aSet.Put( pEditEngine->GetParaAttrib( nPara, nWhich ) );
1013 nWhich++;
1016 return aSet;
1019 void SmTextForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
1021 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1022 if (pEditEngine)
1023 pEditEngine->SetParaAttribs( nPara, rSet );
1026 SfxItemPool* SmTextForwarder::GetPool() const
1028 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1029 return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : nullptr;
1032 void SmTextForwarder::RemoveAttribs( const ESelection& rSelection )
1034 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1035 if (pEditEngine)
1036 pEditEngine->RemoveAttribs( rSelection, false/*bRemoveParaAttribs*/, 0 );
1039 void SmTextForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
1041 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1042 if (pEditEngine)
1043 pEditEngine->GetPortions( nPara, rList );
1046 void SmTextForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
1048 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1049 if (pEditEngine)
1050 pEditEngine->QuickInsertText( rText, rSel );
1053 void SmTextForwarder::QuickInsertLineBreak( const ESelection& rSel )
1055 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1056 if (pEditEngine)
1057 pEditEngine->QuickInsertLineBreak( rSel );
1060 void SmTextForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
1062 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1063 if (pEditEngine)
1064 pEditEngine->QuickInsertField( rFld, rSel );
1067 void SmTextForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
1069 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1070 if (pEditEngine)
1071 pEditEngine->QuickSetAttribs( rSet, rSel );
1074 bool SmTextForwarder::IsValid() const
1076 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1077 // cannot reliably query EditEngine state
1078 // while in the middle of an update
1079 return pEditEngine && pEditEngine->GetUpdateMode();
1082 OUString SmTextForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, Color*& rpTxtColor, Color*& rpFldColor )
1084 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1085 return pEditEngine ? pEditEngine->CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor) : OUString();
1088 void SmTextForwarder::FieldClicked(const SvxFieldItem&, sal_Int32, sal_Int32)
1092 static SfxItemState GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
1094 std::vector<EECharAttrib> aAttribs;
1096 const SfxPoolItem* pLastItem = nullptr;
1098 SfxItemState eState = SfxItemState::DEFAULT;
1100 // check all paragraphs inside the selection
1101 for( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
1103 SfxItemState eParaState = SfxItemState::DEFAULT;
1105 // calculate start and endpos for this paragraph
1106 sal_Int32 nPos = 0;
1107 if( rSel.nStartPara == nPara )
1108 nPos = rSel.nStartPos;
1110 sal_Int32 nEndPos = rSel.nEndPos;
1111 if( rSel.nEndPara != nPara )
1112 nEndPos = rEditEngine.GetTextLen( nPara );
1115 // get list of char attribs
1116 rEditEngine.GetCharAttribs( nPara, aAttribs );
1118 bool bEmpty = true; // we found no item inside the selection of this paragraph
1119 bool bGaps = false; // we found items but theire gaps between them
1120 sal_Int32 nLastEnd = nPos;
1122 const SfxPoolItem* pParaItem = nullptr;
1124 for(std::vector<EECharAttrib>::const_iterator i = aAttribs.begin(); i < aAttribs.end(); ++i)
1126 OSL_ENSURE( i->pAttr, "GetCharAttribs gives corrupt data" );
1128 const bool bEmptyPortion = (i->nStart == i->nEnd);
1129 if( (!bEmptyPortion && (i->nStart >= nEndPos)) || (bEmptyPortion && (i->nStart > nEndPos)) )
1130 break; // break if we are already behind our selection
1132 if( (!bEmptyPortion && (i->nEnd <= nPos)) || (bEmptyPortion && (i->nEnd < nPos)) )
1133 continue; // or if the attribute ends before our selection
1135 if( i->pAttr->Which() != nWhich )
1136 continue; // skip if is not the searched item
1138 // if we already found an item
1139 if( pParaItem )
1141 // ... and its different to this one than the state is don't care
1142 if( *pParaItem != *(i->pAttr) )
1143 return SfxItemState::DONTCARE;
1145 else
1147 pParaItem = i->pAttr;
1150 if( bEmpty )
1151 bEmpty = false;
1153 if( !bGaps && i->nStart > nLastEnd )
1154 bGaps = true;
1156 nLastEnd = i->nEnd;
1159 if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
1160 bGaps = true;
1161 if( bEmpty )
1162 eParaState = SfxItemState::DEFAULT;
1163 else if( bGaps )
1164 eParaState = SfxItemState::DONTCARE;
1165 else
1166 eParaState = SfxItemState::SET;
1168 // if we already found an item check if we found the same
1169 if( pLastItem )
1171 if( (pParaItem == nullptr) || (*pLastItem != *pParaItem) )
1172 return SfxItemState::DONTCARE;
1174 else
1176 pLastItem = pParaItem;
1177 eState = eParaState;
1181 return eState;
1184 SfxItemState SmTextForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
1186 SfxItemState nState = SfxItemState::DISABLED;
1187 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1188 if (pEditEngine)
1189 nState = GetSvxEditEngineItemState( *pEditEngine, rSel, nWhich );
1190 return nState;
1193 SfxItemState SmTextForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
1195 SfxItemState nState = SfxItemState::DISABLED;
1196 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1197 if (pEditEngine)
1199 const SfxItemSet& rSet = pEditEngine->GetParaAttribs( nPara );
1200 nState = rSet.GetItemState( nWhich );
1202 return nState;
1205 LanguageType SmTextForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
1207 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1208 return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex) : LANGUAGE_NONE;
1211 sal_Int32 SmTextForwarder::GetFieldCount( sal_Int32 nPara ) const
1213 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1214 return pEditEngine ? pEditEngine->GetFieldCount(nPara) : 0;
1217 EFieldInfo SmTextForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
1219 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1220 return pEditEngine ? pEditEngine->GetFieldInfo( nPara, nField ) : EFieldInfo();
1223 EBulletInfo SmTextForwarder::GetBulletInfo( sal_Int32 /*nPara*/ ) const
1225 return EBulletInfo();
1228 Rectangle SmTextForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
1230 Rectangle aRect(0,0,0,0);
1231 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1233 if (pEditEngine)
1235 // Handle virtual position one-past-the end of the string
1236 if( nIndex >= pEditEngine->GetTextLen(nPara) )
1238 if( nIndex )
1239 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex-1) );
1241 aRect.Move( aRect.Right() - aRect.Left(), 0 );
1242 aRect.SetSize( Size(1, pEditEngine->GetTextHeight()) );
1244 else
1246 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex) );
1249 return aRect;
1252 Rectangle SmTextForwarder::GetParaBounds( sal_Int32 nPara ) const
1254 Rectangle aRect(0,0,0,0);
1255 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1257 if (pEditEngine)
1259 const Point aPnt = pEditEngine->GetDocPosTopLeft( nPara );
1260 const sal_uLong nWidth = pEditEngine->CalcTextWidth();
1261 const sal_uLong nHeight = pEditEngine->GetTextHeight( nPara );
1262 aRect = Rectangle( aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight );
1265 return aRect;
1268 MapMode SmTextForwarder::GetMapMode() const
1270 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1271 return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode( MapUnit::Map100thMM );
1274 OutputDevice* SmTextForwarder::GetRefDevice() const
1276 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1277 return pEditEngine ? pEditEngine->GetRefDevice() : nullptr;
1280 bool SmTextForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
1282 bool bRes = false;
1283 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1284 if (pEditEngine)
1286 EPosition aDocPos = pEditEngine->FindDocPosition( rPos );
1287 nPara = aDocPos.nPara;
1288 nIndex = aDocPos.nIndex;
1289 bRes = true;
1291 return bRes;
1294 bool SmTextForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
1296 bool bRes = false;
1297 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1298 if (pEditEngine)
1300 ESelection aRes = pEditEngine->GetWord( ESelection(nPara, nIndex, nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD );
1302 if( aRes.nStartPara == nPara &&
1303 aRes.nStartPara == aRes.nEndPara )
1305 nStart = aRes.nStartPos;
1306 nEnd = aRes.nEndPos;
1308 bRes = true;
1312 return bRes;
1315 bool SmTextForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
1317 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1318 return pEditEngine &&
1319 SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex, bInCell );
1322 sal_Int32 SmTextForwarder::GetLineCount( sal_Int32 nPara ) const
1324 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1325 return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
1328 sal_Int32 SmTextForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
1330 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1331 return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
1334 void SmTextForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
1336 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1337 if (pEditEngine)
1338 pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
1339 else
1340 rStart = rEnd = 0;
1343 sal_Int32 SmTextForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
1345 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1346 return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
1349 bool SmTextForwarder::QuickFormatDoc( bool /*bFull*/ )
1351 bool bRes = false;
1352 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1353 if (pEditEngine)
1355 pEditEngine->QuickFormatDoc();
1356 bRes = true;
1358 return bRes;
1361 sal_Int16 SmTextForwarder::GetDepth( sal_Int32 /*nPara*/ ) const
1363 // math has no outliner...
1364 return -1;
1367 bool SmTextForwarder::SetDepth( sal_Int32 /*nPara*/, sal_Int16 nNewDepth )
1369 // math has no outliner...
1370 return -1 == nNewDepth; // is it the value from 'GetDepth' ?
1373 bool SmTextForwarder::Delete( const ESelection& rSelection )
1375 bool bRes = false;
1376 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1377 if (pEditEngine)
1379 pEditEngine->QuickDelete( rSelection );
1380 pEditEngine->QuickFormatDoc();
1381 bRes = true;
1383 return bRes;
1386 bool SmTextForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
1388 bool bRes = false;
1389 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1390 if (pEditEngine)
1392 pEditEngine->QuickInsertText( rStr, rSelection );
1393 pEditEngine->QuickFormatDoc();
1394 bRes = true;
1396 return bRes;
1399 const SfxItemSet* SmTextForwarder::GetEmptyItemSetPtr()
1401 const SfxItemSet *pItemSet = nullptr;
1402 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1403 if (pEditEngine)
1405 pItemSet = &pEditEngine->GetEmptyItemSet();
1407 return pItemSet;
1410 void SmTextForwarder::AppendParagraph()
1412 // append an empty paragraph
1413 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1414 if (pEditEngine)
1416 sal_Int32 nParaCount = pEditEngine->GetParagraphCount();
1417 pEditEngine->InsertParagraph( nParaCount, OUString() );
1421 sal_Int32 SmTextForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet &rSet )
1423 sal_uInt16 nRes = 0;
1424 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1425 if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
1427 // append text
1428 ESelection aSel( nPara, pEditEngine->GetTextLen( nPara ) );
1429 pEditEngine->QuickInsertText( rText, aSel );
1431 // set attributes for new appended text
1432 nRes = aSel.nEndPos = pEditEngine->GetTextLen( nPara );
1433 pEditEngine->QuickSetAttribs( rSet, aSel );
1435 return nRes;
1438 void SmTextForwarder::CopyText(const SvxTextForwarder& rSource)
1441 const SmTextForwarder* pSourceForwarder = dynamic_cast< const SmTextForwarder* >( &rSource );
1442 if( !pSourceForwarder )
1443 return;
1444 EditEngine* pSourceEditEngine = pSourceForwarder->rEditAcc.GetEditEngine();
1445 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1446 if (pEditEngine && pSourceEditEngine )
1448 EditTextObject* pNewTextObject = pSourceEditEngine->CreateTextObject();
1449 pEditEngine->SetText( *pNewTextObject );
1450 delete pNewTextObject;
1455 SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible& rAcc ) :
1456 rEditAcc( rAcc )
1460 SmEditViewForwarder::~SmEditViewForwarder()
1464 bool SmEditViewForwarder::IsValid() const
1466 return rEditAcc.GetEditView() != nullptr;
1469 Rectangle SmEditViewForwarder::GetVisArea() const
1471 Rectangle aRect(0,0,0,0);
1473 EditView *pEditView = rEditAcc.GetEditView();
1474 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
1476 if( pOutDev && pEditView)
1478 Rectangle aVisArea = pEditView->GetVisArea();
1480 // figure out map mode from edit engine
1481 EditEngine* pEditEngine = pEditView->GetEditEngine();
1483 if( pEditEngine )
1485 MapMode aMapMode(pOutDev->GetMapMode());
1486 aVisArea = OutputDevice::LogicToLogic( aVisArea,
1487 pEditEngine->GetRefMapMode(),
1488 aMapMode.GetMapUnit() );
1489 aMapMode.SetOrigin(Point());
1490 aRect = pOutDev->LogicToPixel( aVisArea, aMapMode );
1494 return aRect;
1497 Point SmEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1499 EditView *pEditView = rEditAcc.GetEditView();
1500 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
1502 if( pOutDev )
1504 MapMode aMapMode(pOutDev->GetMapMode());
1505 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
1506 aMapMode.GetMapUnit() ) );
1507 aMapMode.SetOrigin(Point());
1508 return pOutDev->LogicToPixel( aPoint, aMapMode );
1511 return Point();
1514 Point SmEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1516 EditView *pEditView = rEditAcc.GetEditView();
1517 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : nullptr;
1519 if( pOutDev )
1521 MapMode aMapMode(pOutDev->GetMapMode());
1522 aMapMode.SetOrigin(Point());
1523 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
1524 return OutputDevice::LogicToLogic( aPoint,
1525 aMapMode.GetMapUnit(),
1526 rMapMode );
1529 return Point();
1532 bool SmEditViewForwarder::GetSelection( ESelection& rSelection ) const
1534 bool bRes = false;
1535 EditView *pEditView = rEditAcc.GetEditView();
1536 if (pEditView)
1538 rSelection = pEditView->GetSelection();
1539 bRes = true;
1541 return bRes;
1544 bool SmEditViewForwarder::SetSelection( const ESelection& rSelection )
1546 bool bRes = false;
1547 EditView *pEditView = rEditAcc.GetEditView();
1548 if (pEditView)
1550 pEditView->SetSelection( rSelection );
1551 bRes = true;
1553 return bRes;
1556 bool SmEditViewForwarder::Copy()
1558 bool bRes = false;
1559 EditView *pEditView = rEditAcc.GetEditView();
1560 if (pEditView)
1562 pEditView->Copy();
1563 bRes = true;
1565 return bRes;
1568 bool SmEditViewForwarder::Cut()
1570 bool bRes = false;
1571 EditView *pEditView = rEditAcc.GetEditView();
1572 if (pEditView)
1574 pEditView->Cut();
1575 bRes = true;
1577 return bRes;
1580 bool SmEditViewForwarder::Paste()
1582 bool bRes = false;
1583 EditView *pEditView = rEditAcc.GetEditView();
1584 if (pEditView)
1586 pEditView->Paste();
1587 bRes = true;
1589 return bRes;
1593 SmEditAccessible::SmEditAccessible( SmEditWindow *pEditWin ) :
1594 aAccName (SM_RESSTR(STR_CMDBOXWINDOW)),
1595 pTextHelper (),
1596 pWin (pEditWin)
1598 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1601 SmEditAccessible::~SmEditAccessible()
1605 ::accessibility::AccessibleTextHelper *SmEditAccessible::GetTextHelper()
1607 return pTextHelper.get();
1610 void SmEditAccessible::Init()
1612 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1613 if (pWin)
1615 EditEngine *pEditEngine = pWin->GetEditEngine();
1616 EditView *pEditView = pWin->GetEditView();
1617 if (pEditEngine && pEditView)
1619 assert(!pTextHelper);
1620 pTextHelper.reset(new ::accessibility::AccessibleTextHelper( o3tl::make_unique<SmEditSource>( pWin, *this ) ));
1621 pTextHelper->SetEventSource( this );
1626 void SmEditAccessible::ClearWin()
1628 // remove handler before current object gets destroyed
1629 // (avoid handler being called for already dead object)
1630 EditEngine *pEditEngine = GetEditEngine();
1631 if (pEditEngine)
1632 pEditEngine->SetNotifyHdl( Link<EENotify&,void>() );
1634 pWin = nullptr; // implicitly results in AccessibleStateType::DEFUNC set
1636 //! make TextHelper implicitly release C++ references to some core objects
1637 pTextHelper->SetEditSource( ::std::unique_ptr<SvxEditSource>() );
1638 //! make TextHelper release references
1639 //! (e.g. the one set by the 'SetEventSource' call)
1640 pTextHelper->Dispose();
1641 pTextHelper.reset();
1644 // XAccessible
1645 uno::Reference< XAccessibleContext > SAL_CALL SmEditAccessible::getAccessibleContext( )
1646 throw (RuntimeException, std::exception)
1648 SolarMutexGuard aGuard;
1649 return this;
1652 // XAccessibleComponent
1653 sal_Bool SAL_CALL SmEditAccessible::containsPoint( const awt::Point& aPoint )
1654 throw (RuntimeException, std::exception)
1656 //! the arguments coordinates are relativ to the current window !
1657 //! Thus the top left-point is (0, 0)
1659 SolarMutexGuard aGuard;
1660 if (!pWin)
1661 throw RuntimeException();
1663 Size aSz( pWin->GetSizePixel() );
1664 return aPoint.X >= 0 && aPoint.Y >= 0 &&
1665 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
1668 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleAtPoint( const awt::Point& aPoint )
1669 throw (RuntimeException, std::exception)
1671 SolarMutexGuard aGuard;
1672 if (!pTextHelper)
1673 throw RuntimeException();
1674 return pTextHelper->GetAt( aPoint );
1677 awt::Rectangle SAL_CALL SmEditAccessible::getBounds( )
1678 throw (RuntimeException, std::exception)
1680 SolarMutexGuard aGuard;
1681 if (!pWin)
1682 throw RuntimeException();
1683 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1684 "mismatch of window parent and accessible parent" );
1685 return lcl_GetBounds( pWin );
1688 awt::Point SAL_CALL SmEditAccessible::getLocation( )
1689 throw (RuntimeException, std::exception)
1691 SolarMutexGuard aGuard;
1692 if (!pWin)
1693 throw RuntimeException();
1694 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1695 "mismatch of window parent and accessible parent" );
1696 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1697 return awt::Point( aRect.X, aRect.Y );
1700 awt::Point SAL_CALL SmEditAccessible::getLocationOnScreen( )
1701 throw (RuntimeException, std::exception)
1703 SolarMutexGuard aGuard;
1704 if (!pWin)
1705 throw RuntimeException();
1706 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1707 "mismatch of window parent and accessible parent" );
1708 return lcl_GetLocationOnScreen( pWin );
1711 awt::Size SAL_CALL SmEditAccessible::getSize( )
1712 throw (RuntimeException, std::exception)
1714 SolarMutexGuard aGuard;
1715 if (!pWin)
1716 throw RuntimeException();
1717 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1718 "mismatch of window parent and accessible parent" );
1720 Size aSz( pWin->GetSizePixel() );
1721 #if OSL_DEBUG_LEVEL > 0
1722 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1723 Size aSz2( aRect.Width, aRect.Height );
1724 assert(aSz == aSz2 && "mismatch in width");
1725 #endif
1726 return awt::Size( aSz.Width(), aSz.Height() );
1729 void SAL_CALL SmEditAccessible::grabFocus( )
1730 throw (RuntimeException, std::exception)
1732 SolarMutexGuard aGuard;
1733 if (!pWin)
1734 throw RuntimeException();
1736 pWin->GrabFocus();
1739 sal_Int32 SAL_CALL SmEditAccessible::getForeground()
1740 throw (RuntimeException, std::exception)
1742 SolarMutexGuard aGuard;
1744 if (!pWin)
1745 throw RuntimeException();
1746 return static_cast<sal_Int32>(pWin->GetTextColor().GetColor());
1749 sal_Int32 SAL_CALL SmEditAccessible::getBackground()
1750 throw (RuntimeException, std::exception)
1752 SolarMutexGuard aGuard;
1754 if (!pWin)
1755 throw RuntimeException();
1756 Wallpaper aWall( pWin->GetDisplayBackground() );
1757 ColorData nCol;
1758 if (aWall.IsBitmap() || aWall.IsGradient())
1759 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
1760 else
1761 nCol = aWall.GetColor().GetColor();
1762 return static_cast<sal_Int32>(nCol);
1765 // XAccessibleContext
1766 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleChildCount( )
1767 throw (RuntimeException, std::exception)
1769 SolarMutexGuard aGuard;
1770 if (!pTextHelper)
1771 throw RuntimeException();
1772 return pTextHelper->GetChildCount();
1775 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleChild( sal_Int32 i )
1776 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1778 SolarMutexGuard aGuard;
1779 if (!pTextHelper)
1780 throw RuntimeException();
1781 return pTextHelper->GetChild( i );
1784 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleParent( )
1785 throw (RuntimeException, std::exception)
1787 SolarMutexGuard aGuard;
1788 if (!pWin)
1789 throw RuntimeException();
1791 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
1792 OSL_ENSURE( pAccParent, "accessible parent missing" );
1793 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
1796 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleIndexInParent( )
1797 throw (RuntimeException, std::exception)
1799 SolarMutexGuard aGuard;
1800 sal_Int32 nIdx = -1;
1801 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : nullptr;
1802 if (pAccParent)
1804 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
1805 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
1806 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
1807 nIdx = i;
1809 return nIdx;
1812 sal_Int16 SAL_CALL SmEditAccessible::getAccessibleRole( )
1813 throw (RuntimeException, std::exception)
1815 SolarMutexGuard aGuard;
1816 return AccessibleRole::PANEL /*TEXT ?*/;
1819 OUString SAL_CALL SmEditAccessible::getAccessibleDescription( )
1820 throw (RuntimeException, std::exception)
1822 SolarMutexGuard aGuard;
1823 return OUString(); // empty as agreed with product-management
1826 OUString SAL_CALL SmEditAccessible::getAccessibleName( )
1827 throw (RuntimeException, std::exception)
1829 SolarMutexGuard aGuard;
1830 // same name as displayed by the window when not docked
1831 return aAccName;
1834 uno::Reference< XAccessibleRelationSet > SAL_CALL SmEditAccessible::getAccessibleRelationSet( )
1835 throw (RuntimeException, std::exception)
1837 SolarMutexGuard aGuard;
1838 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
1839 return xRelSet; // empty relation set
1842 uno::Reference< XAccessibleStateSet > SAL_CALL SmEditAccessible::getAccessibleStateSet( )
1843 throw (RuntimeException, std::exception)
1845 SolarMutexGuard aGuard;
1846 ::utl::AccessibleStateSetHelper *pStateSet =
1847 new ::utl::AccessibleStateSetHelper;
1849 Reference<XAccessibleStateSet> xStateSet( pStateSet );
1851 if (!pWin || !pTextHelper)
1852 pStateSet->AddState( AccessibleStateType::DEFUNC );
1853 else
1855 pStateSet->AddState( AccessibleStateType::MULTI_LINE );
1856 pStateSet->AddState( AccessibleStateType::ENABLED );
1857 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
1858 if (pWin->HasFocus())
1859 pStateSet->AddState( AccessibleStateType::FOCUSED );
1860 if (pWin->IsActive())
1861 pStateSet->AddState( AccessibleStateType::ACTIVE );
1862 if (pWin->IsVisible())
1863 pStateSet->AddState( AccessibleStateType::SHOWING );
1864 if (pWin->IsReallyVisible())
1865 pStateSet->AddState( AccessibleStateType::VISIBLE );
1866 if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
1867 pStateSet->AddState( AccessibleStateType::OPAQUE );
1870 return xStateSet;
1873 Locale SAL_CALL SmEditAccessible::getLocale( )
1874 throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
1876 SolarMutexGuard aGuard;
1877 // should be the document language...
1878 // We use the language of the localized symbol names here.
1879 return Application::GetSettings().GetUILanguageTag().getLocale();
1883 // XAccessibleEventBroadcaster
1884 void SAL_CALL SmEditAccessible::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1885 throw (RuntimeException, std::exception)
1887 if (pTextHelper) // not disposing (about to destroy view shell)
1888 pTextHelper->AddEventListener( xListener );
1891 void SAL_CALL SmEditAccessible::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1892 throw (RuntimeException, std::exception)
1894 if (pTextHelper) // not disposing (about to destroy view shell)
1895 pTextHelper->RemoveEventListener( xListener );
1898 OUString SAL_CALL SmEditAccessible::getImplementationName()
1899 throw (RuntimeException, std::exception)
1901 return OUString("SmEditAccessible");
1904 sal_Bool SAL_CALL SmEditAccessible::supportsService(
1905 const OUString& rServiceName )
1906 throw (RuntimeException, std::exception)
1908 return cppu::supportsService(this, rServiceName);
1911 Sequence< OUString > SAL_CALL SmEditAccessible::getSupportedServiceNames()
1912 throw (RuntimeException, std::exception)
1914 return Sequence< OUString >{
1915 "css::accessibility::Accessible",
1916 "css::accessibility::AccessibleComponent",
1917 "css::accessibility::AccessibleContext"
1922 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */