bump product version to 5.0.4.1
[LibreOffice.git] / starmath / source / accessibility.cxx
blobd0288ac3b3ab3f33f48a6ec84a388f746d8204e4
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>
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;
70 static awt::Rectangle lcl_GetBounds( vcl::Window *pWin )
72 // !! see VCLXAccessibleComponent::implGetBounds()
74 //! the coordinates returned are relativ to the parent window !
75 //! Thus the top-left point may be different from (0, 0) !
77 awt::Rectangle aBounds;
78 if (pWin)
80 Rectangle aRect = pWin->GetWindowExtentsRelative( NULL );
81 aBounds.X = aRect.Left();
82 aBounds.Y = aRect.Top();
83 aBounds.Width = aRect.GetWidth();
84 aBounds.Height = aRect.GetHeight();
85 vcl::Window* pParent = pWin->GetAccessibleParentWindow();
86 if (pParent)
88 Rectangle aParentRect = pParent->GetWindowExtentsRelative( NULL );
89 awt::Point aParentScreenLoc( aParentRect.Left(), aParentRect.Top() );
90 aBounds.X -= aParentScreenLoc.X;
91 aBounds.Y -= aParentScreenLoc.Y;
94 return aBounds;
97 static awt::Point lcl_GetLocationOnScreen( vcl::Window *pWin )
99 // !! see VCLXAccessibleComponent::getLocationOnScreen()
101 awt::Point aPos;
102 if (pWin)
104 Rectangle aRect = pWin->GetWindowExtentsRelative( NULL );
105 aPos.X = aRect.Left();
106 aPos.Y = aRect.Top();
108 return aPos;
113 SmGraphicAccessible::SmGraphicAccessible( SmGraphicWindow *pGraphicWin ) :
114 aAccName (SM_RESSTR(RID_DOCUMENTSTR)),
115 nClientId (0),
116 pWin (pGraphicWin)
118 OSL_ENSURE( pWin, "SmGraphicAccessible: window missing" );
121 SmGraphicAccessible::~SmGraphicAccessible()
126 SmDocShell * SmGraphicAccessible::GetDoc_Impl()
128 SmViewShell *pView = pWin ? pWin->GetView() : 0;
129 return pView ? pView->GetDoc() : 0;
132 OUString SmGraphicAccessible::GetAccessibleText_Impl()
134 OUString aTxt;
135 SmDocShell *pDoc = GetDoc_Impl();
136 if (pDoc)
137 aTxt = pDoc->GetAccessibleText();
138 return aTxt;
141 void SmGraphicAccessible::ClearWin()
143 pWin = 0; // implicitly results in AccessibleStateType::DEFUNC set
145 if ( nClientId )
147 comphelper::AccessibleEventNotifier::revokeClientNotifyDisposing( nClientId, *this );
148 nClientId = 0;
152 void SmGraphicAccessible::LaunchEvent(
153 const sal_Int16 nAccesibleEventId,
154 const uno::Any &rOldVal,
155 const uno::Any &rNewVal)
157 AccessibleEventObject aEvt;
158 aEvt.Source = (XAccessible *) this;
159 aEvt.EventId = nAccesibleEventId;
160 aEvt.OldValue = rOldVal;
161 aEvt.NewValue = rNewVal ;
163 // pass event on to event-listener's
164 if (nClientId)
165 comphelper::AccessibleEventNotifier::addEvent( nClientId, aEvt );
168 uno::Reference< XAccessibleContext > SAL_CALL SmGraphicAccessible::getAccessibleContext()
169 throw (RuntimeException, std::exception)
171 SolarMutexGuard aGuard;
172 return this;
175 sal_Bool SAL_CALL SmGraphicAccessible::containsPoint( const awt::Point& aPoint )
176 throw (RuntimeException, std::exception)
178 //! the arguments coordinates are relativ to the current window !
179 //! Thus the top-left point is (0, 0)
181 SolarMutexGuard aGuard;
182 if (!pWin)
183 throw RuntimeException();
185 Size aSz( pWin->GetSizePixel() );
186 return aPoint.X >= 0 && aPoint.Y >= 0 &&
187 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
190 uno::Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleAtPoint(
191 const awt::Point& aPoint )
192 throw (RuntimeException, std::exception)
194 SolarMutexGuard aGuard;
195 XAccessible *pRes = 0;
196 if (containsPoint( aPoint ))
197 pRes = this;
198 return pRes;
201 awt::Rectangle SAL_CALL SmGraphicAccessible::getBounds()
202 throw (RuntimeException, std::exception)
204 SolarMutexGuard aGuard;
205 if (!pWin)
206 throw RuntimeException();
207 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
208 "mismatch of window parent and accessible parent" );
209 return lcl_GetBounds( pWin );
212 awt::Point SAL_CALL SmGraphicAccessible::getLocation()
213 throw (RuntimeException, std::exception)
215 SolarMutexGuard aGuard;
216 if (!pWin)
217 throw RuntimeException();
218 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
219 "mismatch of window parent and accessible parent" );
220 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
221 return awt::Point( aRect.X, aRect.Y );
224 awt::Point SAL_CALL SmGraphicAccessible::getLocationOnScreen()
225 throw (RuntimeException, std::exception)
227 SolarMutexGuard aGuard;
228 if (!pWin)
229 throw RuntimeException();
230 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
231 "mismatch of window parent and accessible parent" );
232 return lcl_GetLocationOnScreen( pWin );
235 awt::Size SAL_CALL SmGraphicAccessible::getSize()
236 throw (RuntimeException, std::exception)
238 SolarMutexGuard aGuard;
239 if (!pWin)
240 throw RuntimeException();
241 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
242 "mismatch of window parent and accessible parent" );
244 Size aSz( pWin->GetSizePixel() );
245 #if OSL_DEBUG_LEVEL > 1
246 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
247 Size aSz2( aRect.Width, aRect.Height );
248 OSL_ENSURE( aSz == aSz2, "mismatch in width" );
249 #endif
250 return awt::Size( aSz.Width(), aSz.Height() );
253 void SAL_CALL SmGraphicAccessible::grabFocus()
254 throw (RuntimeException, std::exception)
256 SolarMutexGuard aGuard;
257 if (!pWin)
258 throw RuntimeException();
260 pWin->GrabFocus();
263 sal_Int32 SAL_CALL SmGraphicAccessible::getForeground()
264 throw (RuntimeException, std::exception)
266 SolarMutexGuard aGuard;
268 if (!pWin)
269 throw RuntimeException();
270 return (sal_Int32) pWin->GetTextColor().GetColor();
273 sal_Int32 SAL_CALL SmGraphicAccessible::getBackground()
274 throw (RuntimeException, std::exception)
276 SolarMutexGuard aGuard;
278 if (!pWin)
279 throw RuntimeException();
280 Wallpaper aWall( pWin->GetDisplayBackground() );
281 ColorData nCol;
282 if (aWall.IsBitmap() || aWall.IsGradient())
283 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
284 else
285 nCol = aWall.GetColor().GetColor();
286 return (sal_Int32) nCol;
289 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleChildCount()
290 throw (RuntimeException, std::exception)
292 SolarMutexGuard aGuard;
293 return 0;
296 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleChild(
297 sal_Int32 /*i*/ )
298 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
300 SolarMutexGuard aGuard;
301 throw IndexOutOfBoundsException(); // there is no child...
304 Reference< XAccessible > SAL_CALL SmGraphicAccessible::getAccessibleParent()
305 throw (RuntimeException, std::exception)
307 SolarMutexGuard aGuard;
308 if (!pWin)
309 throw RuntimeException();
311 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
312 OSL_ENSURE( pAccParent, "accessible parent missing" );
313 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
316 sal_Int32 SAL_CALL SmGraphicAccessible::getAccessibleIndexInParent()
317 throw (RuntimeException, std::exception)
319 SolarMutexGuard aGuard;
320 sal_Int32 nIdx = -1;
321 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0;
322 if (pAccParent)
324 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
325 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
326 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
327 nIdx = i;
329 return nIdx;
332 sal_Int16 SAL_CALL SmGraphicAccessible::getAccessibleRole()
333 throw (RuntimeException, std::exception)
335 SolarMutexGuard aGuard;
336 return AccessibleRole::DOCUMENT;
339 OUString SAL_CALL SmGraphicAccessible::getAccessibleDescription()
340 throw (RuntimeException, std::exception)
342 SolarMutexGuard aGuard;
343 SmDocShell *pDoc = GetDoc_Impl();
344 return pDoc ? OUString(pDoc->GetText()) : OUString();
347 OUString SAL_CALL SmGraphicAccessible::getAccessibleName()
348 throw (RuntimeException, std::exception)
350 SolarMutexGuard aGuard;
351 return aAccName;
354 Reference< XAccessibleRelationSet > SAL_CALL SmGraphicAccessible::getAccessibleRelationSet()
355 throw (RuntimeException, std::exception)
357 SolarMutexGuard aGuard;
358 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
359 return xRelSet; // empty relation set
362 Reference< XAccessibleStateSet > SAL_CALL SmGraphicAccessible::getAccessibleStateSet()
363 throw (RuntimeException, std::exception)
365 SolarMutexGuard aGuard;
366 ::utl::AccessibleStateSetHelper *pStateSet =
367 new ::utl::AccessibleStateSetHelper;
369 Reference<XAccessibleStateSet> xStateSet( pStateSet );
371 if (!pWin)
372 pStateSet->AddState( AccessibleStateType::DEFUNC );
373 else
375 pStateSet->AddState( AccessibleStateType::ENABLED );
376 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
377 if (pWin->HasFocus())
378 pStateSet->AddState( AccessibleStateType::FOCUSED );
379 if (pWin->IsActive())
380 pStateSet->AddState( AccessibleStateType::ACTIVE );
381 if (pWin->IsVisible())
382 pStateSet->AddState( AccessibleStateType::SHOWING );
383 if (pWin->IsReallyVisible())
384 pStateSet->AddState( AccessibleStateType::VISIBLE );
385 if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
386 pStateSet->AddState( AccessibleStateType::OPAQUE );
389 return xStateSet;
392 Locale SAL_CALL SmGraphicAccessible::getLocale()
393 throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
395 SolarMutexGuard aGuard;
396 // should be the document language...
397 // We use the language of the localized symbol names here.
398 return Application::GetSettings().GetUILanguageTag().getLocale();
402 void SAL_CALL SmGraphicAccessible::addAccessibleEventListener(
403 const Reference< XAccessibleEventListener >& xListener )
404 throw (RuntimeException, std::exception)
406 if (xListener.is())
408 SolarMutexGuard aGuard;
409 if (pWin)
411 if (!nClientId)
412 nClientId = comphelper::AccessibleEventNotifier::registerClient( );
413 comphelper::AccessibleEventNotifier::addEventListener( nClientId, xListener );
418 void SAL_CALL SmGraphicAccessible::removeAccessibleEventListener(
419 const Reference< XAccessibleEventListener >& xListener )
420 throw (RuntimeException, std::exception)
422 if (xListener.is())
424 SolarMutexGuard aGuard;
425 sal_Int32 nListenerCount = comphelper::AccessibleEventNotifier::removeEventListener( nClientId, xListener );
426 if ( !nListenerCount )
428 // no listeners anymore
429 // -> revoke ourself. This may lead to the notifier thread dying (if we were the last client),
430 // and at least to us not firing any events anymore, in case somebody calls
431 // NotifyAccessibleEvent, again
432 comphelper::AccessibleEventNotifier::revokeClient( nClientId );
433 nClientId = 0;
438 sal_Int32 SAL_CALL SmGraphicAccessible::getCaretPosition()
439 throw (RuntimeException, std::exception)
441 SolarMutexGuard aGuard;
442 return 0;
445 sal_Bool SAL_CALL SmGraphicAccessible::setCaretPosition( sal_Int32 nIndex )
446 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
448 SolarMutexGuard aGuard;
449 OUString aTxt( GetAccessibleText_Impl() );
450 if (!(nIndex < aTxt.getLength()))
451 throw IndexOutOfBoundsException();
452 return sal_False;
455 sal_Unicode SAL_CALL SmGraphicAccessible::getCharacter( sal_Int32 nIndex )
456 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
458 SolarMutexGuard aGuard;
459 OUString aTxt( GetAccessibleText_Impl() );
460 if (!(nIndex < aTxt.getLength()))
461 throw IndexOutOfBoundsException();
462 return aTxt[nIndex];
465 Sequence< beans::PropertyValue > SAL_CALL SmGraphicAccessible::getCharacterAttributes(
466 sal_Int32 nIndex,
467 const uno::Sequence< OUString > & /*rRequestedAttributes*/ )
468 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
470 SolarMutexGuard aGuard;
471 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
472 if (!(0 <= nIndex && nIndex < nLen))
473 throw IndexOutOfBoundsException();
474 return Sequence< beans::PropertyValue >();
477 awt::Rectangle SAL_CALL SmGraphicAccessible::getCharacterBounds( sal_Int32 nIndex )
478 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
480 SolarMutexGuard aGuard;
482 awt::Rectangle aRes;
484 if (!pWin)
485 throw RuntimeException();
486 else
488 // get accessible text
489 SmViewShell *pView = pWin->GetView();
490 SmDocShell *pDoc = pView ? pView->GetDoc() : 0;
491 if (!pDoc)
492 throw RuntimeException();
493 OUString aTxt( GetAccessibleText_Impl() );
494 if (!(0 <= nIndex && nIndex <= aTxt.getLength())) // aTxt.getLength() is valid
495 throw IndexOutOfBoundsException();
497 // find a reasonable rectangle for position aTxt.getLength().
498 bool bWasBehindText = (nIndex == aTxt.getLength());
499 if (bWasBehindText && nIndex)
500 --nIndex;
502 const SmNode *pTree = pDoc->GetFormulaTree();
503 const SmNode *pNode = pTree->FindNodeWithAccessibleIndex( nIndex );
504 //! pNode may be 0 if the index belongs to a char that was inserted
505 //! only for the accessible text!
506 if (pNode)
508 sal_Int32 nAccIndex = pNode->GetAccessibleIndex();
509 OSL_ENSURE( nAccIndex >= 0, "invalid accessible index" );
510 OSL_ENSURE( nIndex >= nAccIndex, "index out of range" );
512 OUStringBuffer aBuf;
513 pNode->GetAccessibleText(aBuf);
514 OUString aNodeText = aBuf.makeStringAndClear();
515 sal_Int32 nNodeIndex = nIndex - nAccIndex;
516 if (0 <= nNodeIndex && nNodeIndex < aNodeText.getLength())
518 // get appropriate rectangle
519 Point aOffset(pNode->GetTopLeft() - pTree->GetTopLeft());
520 Point aTLPos (pWin->GetFormulaDrawPos() + aOffset);
521 aTLPos.X() -= 0;
522 Size aSize (pNode->GetSize());
524 long* pXAry = new long[ aNodeText.getLength() ];
525 pWin->SetFont( pNode->GetFont() );
526 pWin->GetTextArray( aNodeText, pXAry, 0, aNodeText.getLength() );
527 aTLPos.X() += nNodeIndex > 0 ? pXAry[nNodeIndex - 1] : 0;
528 aSize.Width() = nNodeIndex > 0 ? pXAry[nNodeIndex] - pXAry[nNodeIndex - 1] : pXAry[nNodeIndex];
529 delete[] pXAry;
531 aTLPos = pWin->LogicToPixel( aTLPos );
532 aSize = pWin->LogicToPixel( aSize );
533 aRes.X = aTLPos.X();
534 aRes.Y = aTLPos.Y();
535 aRes.Width = aSize.Width();
536 aRes.Height = aSize.Height();
540 // take rectangle from last character and move it to the right
541 if (bWasBehindText)
542 aRes.X += aRes.Width;
545 return aRes;
548 sal_Int32 SAL_CALL SmGraphicAccessible::getCharacterCount()
549 throw (RuntimeException, std::exception)
551 SolarMutexGuard aGuard;
552 return GetAccessibleText_Impl().getLength();
555 sal_Int32 SAL_CALL SmGraphicAccessible::getIndexAtPoint( const awt::Point& aPoint )
556 throw (RuntimeException, std::exception)
558 SolarMutexGuard aGuard;
560 sal_Int32 nRes = -1;
561 if (pWin)
563 const SmNode *pTree = pWin->GetView()->GetDoc()->GetFormulaTree();
564 // can be NULL! e.g. if one clicks within the window already during loading of the
565 // document (before the parser even started)
566 if (!pTree)
567 return nRes;
569 // get position relative to formula draw position
570 Point aPos( aPoint.X, aPoint.Y );
571 aPos = pWin->PixelToLogic( aPos );
572 aPos -= pWin->GetFormulaDrawPos();
574 // if it was inside the formula then get the appropriate node
575 const SmNode *pNode = 0;
576 if (pTree->OrientedDist(aPos) <= 0)
577 pNode = pTree->FindRectClosestTo(aPos);
579 if (pNode)
581 // get appropriate rectangle
582 Point aOffset( pNode->GetTopLeft() - pTree->GetTopLeft() );
583 Point aTLPos ( aOffset );
584 aTLPos.X() -= 0;
585 Size aSize( pNode->GetSize() );
587 Rectangle aRect( aTLPos, aSize );
588 if (aRect.IsInside( aPos ))
590 OSL_ENSURE( pNode->IsVisible(), "node is not a leaf" );
591 OUStringBuffer aBuf;
592 pNode->GetAccessibleText(aBuf);
593 OUString aTxt = aBuf.makeStringAndClear();
594 OSL_ENSURE( !aTxt.isEmpty(), "no accessible text available" );
596 long nNodeX = pNode->GetLeft();
598 long* pXAry = new long[ aTxt.getLength() ];
599 pWin->SetFont( pNode->GetFont() );
600 pWin->GetTextArray( aTxt, pXAry, 0, aTxt.getLength() );
601 for (sal_Int32 i = 0; i < aTxt.getLength() && nRes == -1; ++i)
603 if (pXAry[i] + nNodeX > aPos.X())
604 nRes = i;
606 delete[] pXAry;
607 OSL_ENSURE( nRes >= 0 && nRes < aTxt.getLength(), "index out of range" );
608 OSL_ENSURE( pNode->GetAccessibleIndex() >= 0,
609 "invalid accessible index" );
611 nRes = pNode->GetAccessibleIndex() + nRes;
615 return nRes;
618 OUString SAL_CALL SmGraphicAccessible::getSelectedText()
619 throw (RuntimeException, std::exception)
621 SolarMutexGuard aGuard;
622 return OUString();
625 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionStart()
626 throw (RuntimeException, std::exception)
628 SolarMutexGuard aGuard;
629 return -1;
632 sal_Int32 SAL_CALL SmGraphicAccessible::getSelectionEnd()
633 throw (RuntimeException, std::exception)
635 SolarMutexGuard aGuard;
636 return -1;
639 sal_Bool SAL_CALL SmGraphicAccessible::setSelection(
640 sal_Int32 nStartIndex,
641 sal_Int32 nEndIndex )
642 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
644 SolarMutexGuard aGuard;
645 sal_Int32 nLen = GetAccessibleText_Impl().getLength();
646 if (!(0 <= nStartIndex && nStartIndex < nLen) ||
647 !(0 <= nEndIndex && nEndIndex < nLen))
648 throw IndexOutOfBoundsException();
649 return sal_False;
652 OUString SAL_CALL SmGraphicAccessible::getText()
653 throw (RuntimeException, std::exception)
655 SolarMutexGuard aGuard;
656 return GetAccessibleText_Impl();
659 OUString SAL_CALL SmGraphicAccessible::getTextRange(
660 sal_Int32 nStartIndex,
661 sal_Int32 nEndIndex )
662 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
664 //!! nEndIndex may be the string length per definition of the interface !!
665 //!! text should be copied exclusive that end index though. And arguments
666 //!! may be switched.
668 SolarMutexGuard aGuard;
669 OUString aTxt( GetAccessibleText_Impl() );
670 sal_Int32 nStart = std::min(nStartIndex, nEndIndex);
671 sal_Int32 nEnd = std::max(nStartIndex, nEndIndex);
672 if (!(nStart <= aTxt.getLength()) ||
673 !(nEnd <= aTxt.getLength()))
674 throw IndexOutOfBoundsException();
675 return aTxt.copy( nStart, nEnd - nStart );
678 ::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
680 SolarMutexGuard aGuard;
681 OUString aTxt( GetAccessibleText_Impl() );
682 //!! nIndex is allowed to be the string length
683 if (!(nIndex <= aTxt.getLength()))
684 throw IndexOutOfBoundsException();
686 ::com::sun::star::accessibility::TextSegment aResult;
687 aResult.SegmentStart = -1;
688 aResult.SegmentEnd = -1;
689 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
691 aResult.SegmentText = aTxt.copy(nIndex, 1);
692 aResult.SegmentStart = nIndex;
693 aResult.SegmentEnd = nIndex+1;
695 return aResult;
698 ::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
700 SolarMutexGuard aGuard;
701 OUString aTxt( GetAccessibleText_Impl() );
702 //!! nIndex is allowed to be the string length
703 if (!(nIndex <= aTxt.getLength()))
704 throw IndexOutOfBoundsException();
706 ::com::sun::star::accessibility::TextSegment aResult;
707 aResult.SegmentStart = -1;
708 aResult.SegmentEnd = -1;
710 if ( (AccessibleTextType::CHARACTER == aTextType) && nIndex )
712 aResult.SegmentText = aTxt.copy(nIndex-1, 1);
713 aResult.SegmentStart = nIndex-1;
714 aResult.SegmentEnd = nIndex;
716 return aResult;
719 ::com::sun::star::accessibility::TextSegment SAL_CALL SmGraphicAccessible::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException, std::exception)
721 SolarMutexGuard aGuard;
722 OUString aTxt( GetAccessibleText_Impl() );
723 //!! nIndex is allowed to be the string length
724 if (!(nIndex <= aTxt.getLength()))
725 throw IndexOutOfBoundsException();
727 ::com::sun::star::accessibility::TextSegment aResult;
728 aResult.SegmentStart = -1;
729 aResult.SegmentEnd = -1;
731 nIndex++; // text *behind*
732 if ( (AccessibleTextType::CHARACTER == aTextType) && (nIndex < aTxt.getLength()) )
734 aResult.SegmentText = aTxt.copy(nIndex, 1);
735 aResult.SegmentStart = nIndex;
736 aResult.SegmentEnd = nIndex+1;
738 return aResult;
741 sal_Bool SAL_CALL SmGraphicAccessible::copyText(
742 sal_Int32 nStartIndex,
743 sal_Int32 nEndIndex )
744 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
746 SolarMutexGuard aGuard;
747 bool bReturn = false;
749 if (!pWin)
750 throw RuntimeException();
751 else
753 Reference< datatransfer::clipboard::XClipboard > xClipboard = pWin->GetClipboard();
754 if ( xClipboard.is() )
756 OUString sText( getTextRange(nStartIndex, nEndIndex) );
758 vcl::unohelper::TextDataObject* pDataObj = new vcl::unohelper::TextDataObject( sText );
759 SolarMutexReleaser aReleaser;
760 xClipboard->setContents( pDataObj, NULL );
762 Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
763 if( xFlushableClipboard.is() )
764 xFlushableClipboard->flushClipboard();
766 bReturn = true;
770 return bReturn;
773 OUString SAL_CALL SmGraphicAccessible::getImplementationName()
774 throw (RuntimeException, std::exception)
776 return OUString("SmGraphicAccessible");
779 sal_Bool SAL_CALL SmGraphicAccessible::supportsService(
780 const OUString& rServiceName )
781 throw (RuntimeException, std::exception)
783 return cppu::supportsService(this, rServiceName);
786 Sequence< OUString > SAL_CALL SmGraphicAccessible::getSupportedServiceNames()
787 throw (RuntimeException, std::exception)
789 return Sequence< OUString >{
790 "com::sun::star::accessibility::Accessible",
791 "com::sun::star::accessibility::AccessibleComponent",
792 "com::sun::star::accessibility::AccessibleContext",
793 "com::sun::star::accessibility::AccessibleText"
801 SmEditSource::SmEditSource( SmEditWindow * /*pWin*/, SmEditAccessible &rAcc ) :
802 aViewFwd (rAcc),
803 aTextFwd (rAcc, *this),
804 aEditViewFwd(rAcc),
805 rEditAcc (rAcc)
809 SmEditSource::SmEditSource( const SmEditSource &rSrc ) :
810 SvxEditSource(),
811 aViewFwd (rSrc.rEditAcc),
812 aTextFwd (rSrc.rEditAcc, *this),
813 aEditViewFwd(rSrc.rEditAcc),
814 rEditAcc (rSrc.rEditAcc)
818 SmEditSource::~SmEditSource()
822 SvxEditSource* SmEditSource::Clone() const
824 return new SmEditSource( *this );
827 SvxTextForwarder* SmEditSource::GetTextForwarder()
829 return &aTextFwd;
832 SvxViewForwarder* SmEditSource::GetViewForwarder()
834 return &aViewFwd;
837 SvxEditViewForwarder* SmEditSource::GetEditViewForwarder( bool /*bCreate*/ )
839 return &aEditViewFwd;
842 void SmEditSource::UpdateData()
844 // would possibly only by needed if the XText interface is implemented
845 // and its text needs to be updated.
848 SfxBroadcaster & SmEditSource::GetBroadcaster() const
850 return const_cast<SmEditSource*>(this)->aBroadCaster;
853 SmViewForwarder::SmViewForwarder( SmEditAccessible &rAcc ) :
854 rEditAcc(rAcc)
858 SmViewForwarder::~SmViewForwarder()
862 bool SmViewForwarder::IsValid() const
864 return rEditAcc.GetEditView() != 0;
867 Rectangle SmViewForwarder::GetVisArea() const
869 EditView *pEditView = rEditAcc.GetEditView();
870 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
872 if( pOutDev && pEditView)
874 Rectangle aVisArea = pEditView->GetVisArea();
876 // figure out map mode from edit engine
877 EditEngine* pEditEngine = pEditView->GetEditEngine();
879 if( pEditEngine )
881 MapMode aMapMode(pOutDev->GetMapMode());
882 aVisArea = OutputDevice::LogicToLogic( aVisArea,
883 pEditEngine->GetRefMapMode(),
884 aMapMode.GetMapUnit() );
885 aMapMode.SetOrigin(Point());
886 return pOutDev->LogicToPixel( aVisArea, aMapMode );
890 return Rectangle();
893 Point SmViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
895 EditView *pEditView = rEditAcc.GetEditView();
896 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
898 if( pOutDev )
900 MapMode aMapMode(pOutDev->GetMapMode());
901 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
902 aMapMode.GetMapUnit() ) );
903 aMapMode.SetOrigin(Point());
904 return pOutDev->LogicToPixel( aPoint, aMapMode );
907 return Point();
910 Point SmViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
912 EditView *pEditView = rEditAcc.GetEditView();
913 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
915 if( pOutDev )
917 MapMode aMapMode(pOutDev->GetMapMode());
918 aMapMode.SetOrigin(Point());
919 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
920 return OutputDevice::LogicToLogic( aPoint,
921 aMapMode.GetMapUnit(),
922 rMapMode );
925 return Point();
931 SmTextForwarder::SmTextForwarder( SmEditAccessible& rAcc, SmEditSource & rSource) :
932 rEditAcc ( rAcc ),
933 rEditSource (rSource)
935 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
936 if (pEditEngine)
937 pEditEngine->SetNotifyHdl( LINK(this, SmTextForwarder, NotifyHdl) );
940 SmTextForwarder::~SmTextForwarder()
942 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
943 if (pEditEngine)
944 pEditEngine->SetNotifyHdl( Link<>() );
947 IMPL_LINK(SmTextForwarder, NotifyHdl, EENotify*, aNotify)
949 if (aNotify)
951 ::std::unique_ptr< SfxHint > aHint = SvxEditSourceHelper::EENotification2Hint( aNotify );
952 if (aHint.get())
953 rEditSource.GetBroadcaster().Broadcast( *aHint.get() );
956 return 0;
959 sal_Int32 SmTextForwarder::GetParagraphCount() const
961 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
962 return pEditEngine ? pEditEngine->GetParagraphCount() : 0;
965 sal_Int32 SmTextForwarder::GetTextLen( sal_Int32 nParagraph ) const
967 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
968 return pEditEngine ? pEditEngine->GetTextLen( nParagraph ) : 0;
971 OUString SmTextForwarder::GetText( const ESelection& rSel ) const
973 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
974 OUString aRet;
975 if (pEditEngine)
976 aRet = pEditEngine->GetText( rSel, LINEEND_LF );
977 return convertLineEnd(aRet, GetSystemLineEnd());
980 SfxItemSet SmTextForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
982 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
983 OSL_ENSURE( pEditEngine, "EditEngine missing" );
984 if( rSel.nStartPara == rSel.nEndPara )
986 GetAttribsFlags nFlags = GetAttribsFlags::NONE;
987 switch( nOnlyHardAttrib )
989 case EditEngineAttribs_All:
990 nFlags = GetAttribsFlags::ALL;
991 break;
992 case EditEngineAttribs_HardAndPara:
993 nFlags = GetAttribsFlags::PARAATTRIBS|GetAttribsFlags::CHARATTRIBS;
994 break;
995 case EditEngineAttribs_OnlyHard:
996 nFlags = GetAttribsFlags::CHARATTRIBS;
997 break;
998 default:
999 SAL_WARN("starmath", "unknown flags for SmTextForwarder::GetAttribs");
1002 return pEditEngine->GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
1004 else
1006 return pEditEngine->GetAttribs( rSel, nOnlyHardAttrib );
1010 SfxItemSet SmTextForwarder::GetParaAttribs( sal_Int32 nPara ) const
1012 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1013 OSL_ENSURE( pEditEngine, "EditEngine missing" );
1015 SfxItemSet aSet( pEditEngine->GetParaAttribs( nPara ) );
1017 sal_uInt16 nWhich = EE_PARA_START;
1018 while( nWhich <= EE_PARA_END )
1020 if( aSet.GetItemState( nWhich, true ) != SfxItemState::SET )
1022 if( pEditEngine->HasParaAttrib( nPara, nWhich ) )
1023 aSet.Put( pEditEngine->GetParaAttrib( nPara, nWhich ) );
1025 nWhich++;
1028 return aSet;
1031 void SmTextForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
1033 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1034 if (pEditEngine)
1035 pEditEngine->SetParaAttribs( nPara, rSet );
1038 SfxItemPool* SmTextForwarder::GetPool() const
1040 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1041 return pEditEngine ? pEditEngine->GetEmptyItemSet().GetPool() : 0;
1044 void SmTextForwarder::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAttribs, sal_uInt16 nWhich )
1046 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1047 if (pEditEngine)
1048 pEditEngine->RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich );
1051 void SmTextForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
1053 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1054 if (pEditEngine)
1055 pEditEngine->GetPortions( nPara, rList );
1058 void SmTextForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
1060 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1061 if (pEditEngine)
1062 pEditEngine->QuickInsertText( rText, rSel );
1065 void SmTextForwarder::QuickInsertLineBreak( const ESelection& rSel )
1067 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1068 if (pEditEngine)
1069 pEditEngine->QuickInsertLineBreak( rSel );
1072 void SmTextForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
1074 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1075 if (pEditEngine)
1076 pEditEngine->QuickInsertField( rFld, rSel );
1079 void SmTextForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
1081 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1082 if (pEditEngine)
1083 pEditEngine->QuickSetAttribs( rSet, rSel );
1086 bool SmTextForwarder::IsValid() const
1088 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1089 // cannot reliably query EditEngine state
1090 // while in the middle of an update
1091 return pEditEngine && pEditEngine->GetUpdateMode();
1094 OUString SmTextForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, Color*& rpTxtColor, Color*& rpFldColor )
1096 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1097 return pEditEngine ? pEditEngine->CalcFieldValue(rField, nPara, nPos, rpTxtColor, rpFldColor) : OUString();
1100 void SmTextForwarder::FieldClicked(const SvxFieldItem&, sal_Int32, sal_Int32)
1104 static SfxItemState GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
1106 std::vector<EECharAttrib> aAttribs;
1108 const SfxPoolItem* pLastItem = NULL;
1110 SfxItemState eState = SfxItemState::DEFAULT;
1112 // check all paragraphs inside the selection
1113 for( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
1115 SfxItemState eParaState = SfxItemState::DEFAULT;
1117 // calculate start and endpos for this paragraph
1118 sal_Int32 nPos = 0;
1119 if( rSel.nStartPara == nPara )
1120 nPos = rSel.nStartPos;
1122 sal_Int32 nEndPos = rSel.nEndPos;
1123 if( rSel.nEndPara != nPara )
1124 nEndPos = rEditEngine.GetTextLen( nPara );
1127 // get list of char attribs
1128 rEditEngine.GetCharAttribs( nPara, aAttribs );
1130 bool bEmpty = true; // we found no item inside the selection of this paragraph
1131 bool bGaps = false; // we found items but theire gaps between them
1132 sal_Int32 nLastEnd = nPos;
1134 const SfxPoolItem* pParaItem = NULL;
1136 for(std::vector<EECharAttrib>::const_iterator i = aAttribs.begin(); i < aAttribs.end(); ++i)
1138 OSL_ENSURE( i->pAttr, "GetCharAttribs gives corrupt data" );
1140 const bool bEmptyPortion = (i->nStart == i->nEnd);
1141 if( (!bEmptyPortion && (i->nStart >= nEndPos)) || (bEmptyPortion && (i->nStart > nEndPos)) )
1142 break; // break if we are already behind our selection
1144 if( (!bEmptyPortion && (i->nEnd <= nPos)) || (bEmptyPortion && (i->nEnd < nPos)) )
1145 continue; // or if the attribute ends before our selection
1147 if( i->pAttr->Which() != nWhich )
1148 continue; // skip if is not the searched item
1150 // if we already found an item
1151 if( pParaItem )
1153 // ... and its different to this one than the state is dont care
1154 if( *pParaItem != *(i->pAttr) )
1155 return SfxItemState::DONTCARE;
1157 else
1159 pParaItem = i->pAttr;
1162 if( bEmpty )
1163 bEmpty = false;
1165 if( !bGaps && i->nStart > nLastEnd )
1166 bGaps = true;
1168 nLastEnd = i->nEnd;
1171 if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
1172 bGaps = true;
1173 if( bEmpty )
1174 eParaState = SfxItemState::DEFAULT;
1175 else if( bGaps )
1176 eParaState = SfxItemState::DONTCARE;
1177 else
1178 eParaState = SfxItemState::SET;
1180 // if we already found an item check if we found the same
1181 if( pLastItem )
1183 if( (pParaItem == NULL) || (*pLastItem != *pParaItem) )
1184 return SfxItemState::DONTCARE;
1186 else
1188 pLastItem = pParaItem;
1189 eState = eParaState;
1193 return eState;
1196 SfxItemState SmTextForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
1198 SfxItemState nState = SfxItemState::DISABLED;
1199 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1200 if (pEditEngine)
1201 nState = GetSvxEditEngineItemState( *pEditEngine, rSel, nWhich );
1202 return nState;
1205 SfxItemState SmTextForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
1207 SfxItemState nState = SfxItemState::DISABLED;
1208 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1209 if (pEditEngine)
1211 const SfxItemSet& rSet = pEditEngine->GetParaAttribs( nPara );
1212 nState = rSet.GetItemState( nWhich );
1214 return nState;
1217 LanguageType SmTextForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
1219 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1220 return pEditEngine ? pEditEngine->GetLanguage(nPara, nIndex) : LANGUAGE_NONE;
1223 sal_Int32 SmTextForwarder::GetFieldCount( sal_Int32 nPara ) const
1225 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1226 return pEditEngine ? pEditEngine->GetFieldCount(nPara) : 0;
1229 EFieldInfo SmTextForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
1231 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1232 return pEditEngine ? pEditEngine->GetFieldInfo( nPara, nField ) : EFieldInfo();
1235 EBulletInfo SmTextForwarder::GetBulletInfo( sal_Int32 /*nPara*/ ) const
1237 return EBulletInfo();
1240 Rectangle SmTextForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
1242 Rectangle aRect(0,0,0,0);
1243 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1245 if (pEditEngine)
1247 // Handle virtual position one-past-the end of the string
1248 if( nIndex >= pEditEngine->GetTextLen(nPara) )
1250 if( nIndex )
1251 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex-1) );
1253 aRect.Move( aRect.Right() - aRect.Left(), 0 );
1254 aRect.SetSize( Size(1, pEditEngine->GetTextHeight()) );
1256 else
1258 aRect = pEditEngine->GetCharacterBounds( EPosition(nPara, nIndex) );
1261 return aRect;
1264 Rectangle SmTextForwarder::GetParaBounds( sal_Int32 nPara ) const
1266 Rectangle aRect(0,0,0,0);
1267 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1269 if (pEditEngine)
1271 const Point aPnt = pEditEngine->GetDocPosTopLeft( nPara );
1272 const sal_uLong nWidth = pEditEngine->CalcTextWidth();
1273 const sal_uLong nHeight = pEditEngine->GetTextHeight( nPara );
1274 aRect = Rectangle( aPnt.X(), aPnt.Y(), aPnt.X() + nWidth, aPnt.Y() + nHeight );
1277 return aRect;
1280 MapMode SmTextForwarder::GetMapMode() const
1282 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1283 return pEditEngine ? pEditEngine->GetRefMapMode() : MapMode( MAP_100TH_MM );
1286 OutputDevice* SmTextForwarder::GetRefDevice() const
1288 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1289 return pEditEngine ? pEditEngine->GetRefDevice() : 0;
1292 bool SmTextForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
1294 bool bRes = false;
1295 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1296 if (pEditEngine)
1298 EPosition aDocPos = pEditEngine->FindDocPosition( rPos );
1299 nPara = aDocPos.nPara;
1300 nIndex = aDocPos.nIndex;
1301 bRes = true;
1303 return bRes;
1306 bool SmTextForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
1308 bool bRes = false;
1309 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1310 if (pEditEngine)
1312 ESelection aRes = pEditEngine->GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD );
1314 if( aRes.nStartPara == nPara &&
1315 aRes.nStartPara == aRes.nEndPara )
1317 nStart = aRes.nStartPos;
1318 nEnd = aRes.nEndPos;
1320 bRes = true;
1324 return bRes;
1327 bool SmTextForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
1329 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1330 return pEditEngine &&
1331 SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, *pEditEngine, nPara, nIndex, bInCell );
1334 sal_Int32 SmTextForwarder::GetLineCount( sal_Int32 nPara ) const
1336 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1337 return pEditEngine ? pEditEngine->GetLineCount(nPara) : 0;
1340 sal_Int32 SmTextForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
1342 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1343 return pEditEngine ? pEditEngine->GetLineLen(nPara, nLine) : 0;
1346 void SmTextForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
1348 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1349 if (pEditEngine)
1350 pEditEngine->GetLineBoundaries(rStart, rEnd, nPara, nLine);
1351 else
1352 rStart = rEnd = 0;
1355 sal_Int32 SmTextForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
1357 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1358 return pEditEngine ? pEditEngine->GetLineNumberAtIndex(nPara, nIndex) : 0;
1361 bool SmTextForwarder::QuickFormatDoc( bool /*bFull*/ )
1363 bool bRes = false;
1364 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1365 if (pEditEngine)
1367 pEditEngine->QuickFormatDoc();
1368 bRes = true;
1370 return bRes;
1373 sal_Int16 SmTextForwarder::GetDepth( sal_Int32 /*nPara*/ ) const
1375 // math has no outliner...
1376 return -1;
1379 bool SmTextForwarder::SetDepth( sal_Int32 /*nPara*/, sal_Int16 nNewDepth )
1381 // math has no outliner...
1382 return -1 == nNewDepth; // is it the value from 'GetDepth' ?
1385 bool SmTextForwarder::Delete( const ESelection& rSelection )
1387 bool bRes = false;
1388 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1389 if (pEditEngine)
1391 pEditEngine->QuickDelete( rSelection );
1392 pEditEngine->QuickFormatDoc();
1393 bRes = true;
1395 return bRes;
1398 bool SmTextForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
1400 bool bRes = false;
1401 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1402 if (pEditEngine)
1404 pEditEngine->QuickInsertText( rStr, rSelection );
1405 pEditEngine->QuickFormatDoc();
1406 bRes = true;
1408 return bRes;
1411 const SfxItemSet* SmTextForwarder::GetEmptyItemSetPtr()
1413 const SfxItemSet *pItemSet = 0;
1414 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1415 if (pEditEngine)
1417 pItemSet = &pEditEngine->GetEmptyItemSet();
1419 return pItemSet;
1422 void SmTextForwarder::AppendParagraph()
1424 // append an empty paragraph
1425 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1426 if (pEditEngine)
1428 sal_Int32 nParaCount = pEditEngine->GetParagraphCount();
1429 pEditEngine->InsertParagraph( nParaCount, OUString() );
1433 sal_Int32 SmTextForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet &rSet )
1435 sal_uInt16 nRes = 0;
1436 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1437 if (pEditEngine && nPara < pEditEngine->GetParagraphCount())
1439 // append text
1440 ESelection aSel( nPara, pEditEngine->GetTextLen( nPara ) );
1441 pEditEngine->QuickInsertText( rText, aSel );
1443 // set attributes for new appended text
1444 nRes = aSel.nEndPos = pEditEngine->GetTextLen( nPara );
1445 pEditEngine->QuickSetAttribs( rSet, aSel );
1447 return nRes;
1450 void SmTextForwarder::CopyText(const SvxTextForwarder& rSource)
1453 const SmTextForwarder* pSourceForwarder = dynamic_cast< const SmTextForwarder* >( &rSource );
1454 if( !pSourceForwarder )
1455 return;
1456 EditEngine* pSourceEditEngine = pSourceForwarder->rEditAcc.GetEditEngine();
1457 EditEngine *pEditEngine = rEditAcc.GetEditEngine();
1458 if (pEditEngine && pSourceEditEngine )
1460 EditTextObject* pNewTextObject = pSourceEditEngine->CreateTextObject();
1461 pEditEngine->SetText( *pNewTextObject );
1462 delete pNewTextObject;
1468 SmEditViewForwarder::SmEditViewForwarder( SmEditAccessible& rAcc ) :
1469 rEditAcc( rAcc )
1473 SmEditViewForwarder::~SmEditViewForwarder()
1477 bool SmEditViewForwarder::IsValid() const
1479 return rEditAcc.GetEditView() != 0;
1482 Rectangle SmEditViewForwarder::GetVisArea() const
1484 Rectangle aRect(0,0,0,0);
1486 EditView *pEditView = rEditAcc.GetEditView();
1487 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
1489 if( pOutDev && pEditView)
1491 Rectangle aVisArea = pEditView->GetVisArea();
1493 // figure out map mode from edit engine
1494 EditEngine* pEditEngine = pEditView->GetEditEngine();
1496 if( pEditEngine )
1498 MapMode aMapMode(pOutDev->GetMapMode());
1499 aVisArea = OutputDevice::LogicToLogic( aVisArea,
1500 pEditEngine->GetRefMapMode(),
1501 aMapMode.GetMapUnit() );
1502 aMapMode.SetOrigin(Point());
1503 aRect = pOutDev->LogicToPixel( aVisArea, aMapMode );
1507 return aRect;
1510 Point SmEditViewForwarder::LogicToPixel( const Point& rPoint, const MapMode& rMapMode ) const
1512 EditView *pEditView = rEditAcc.GetEditView();
1513 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
1515 if( pOutDev )
1517 MapMode aMapMode(pOutDev->GetMapMode());
1518 Point aPoint( OutputDevice::LogicToLogic( rPoint, rMapMode,
1519 aMapMode.GetMapUnit() ) );
1520 aMapMode.SetOrigin(Point());
1521 return pOutDev->LogicToPixel( aPoint, aMapMode );
1524 return Point();
1527 Point SmEditViewForwarder::PixelToLogic( const Point& rPoint, const MapMode& rMapMode ) const
1529 EditView *pEditView = rEditAcc.GetEditView();
1530 OutputDevice* pOutDev = pEditView ? pEditView->GetWindow() : 0;
1532 if( pOutDev )
1534 MapMode aMapMode(pOutDev->GetMapMode());
1535 aMapMode.SetOrigin(Point());
1536 Point aPoint( pOutDev->PixelToLogic( rPoint, aMapMode ) );
1537 return OutputDevice::LogicToLogic( aPoint,
1538 aMapMode.GetMapUnit(),
1539 rMapMode );
1542 return Point();
1545 bool SmEditViewForwarder::GetSelection( ESelection& rSelection ) const
1547 bool bRes = false;
1548 EditView *pEditView = rEditAcc.GetEditView();
1549 if (pEditView)
1551 rSelection = pEditView->GetSelection();
1552 bRes = true;
1554 return bRes;
1557 bool SmEditViewForwarder::SetSelection( const ESelection& rSelection )
1559 bool bRes = false;
1560 EditView *pEditView = rEditAcc.GetEditView();
1561 if (pEditView)
1563 pEditView->SetSelection( rSelection );
1564 bRes = true;
1566 return bRes;
1569 bool SmEditViewForwarder::Copy()
1571 bool bRes = false;
1572 EditView *pEditView = rEditAcc.GetEditView();
1573 if (pEditView)
1575 pEditView->Copy();
1576 bRes = true;
1578 return bRes;
1581 bool SmEditViewForwarder::Cut()
1583 bool bRes = false;
1584 EditView *pEditView = rEditAcc.GetEditView();
1585 if (pEditView)
1587 pEditView->Cut();
1588 bRes = true;
1590 return bRes;
1593 bool SmEditViewForwarder::Paste()
1595 bool bRes = false;
1596 EditView *pEditView = rEditAcc.GetEditView();
1597 if (pEditView)
1599 pEditView->Paste();
1600 bRes = true;
1602 return bRes;
1607 SmEditAccessible::SmEditAccessible( SmEditWindow *pEditWin ) :
1608 aAccName (SM_RESSTR(STR_CMDBOXWINDOW)),
1609 pTextHelper (0),
1610 pWin (pEditWin)
1612 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1615 SmEditAccessible::~SmEditAccessible()
1617 delete pTextHelper;
1620 void SmEditAccessible::Init()
1622 OSL_ENSURE( pWin, "SmEditAccessible: window missing" );
1623 if (pWin)
1625 EditEngine *pEditEngine = pWin->GetEditEngine();
1626 EditView *pEditView = pWin->GetEditView();
1627 if (pEditEngine && pEditView)
1629 ::std::unique_ptr< SvxEditSource > pEditSource(
1630 new SmEditSource( pWin, *this ) );
1631 pTextHelper = new ::accessibility::AccessibleTextHelper( std::move(pEditSource) );
1632 pTextHelper->SetEventSource( this );
1637 void SmEditAccessible::ClearWin()
1639 // remove handler before current object gets destroyed
1640 // (avoid handler being called for already dead object)
1641 EditEngine *pEditEngine = GetEditEngine();
1642 if (pEditEngine)
1643 pEditEngine->SetNotifyHdl( Link<>() );
1645 pWin = 0; // implicitly results in AccessibleStateType::DEFUNC set
1647 //! make TextHelper implicitly release C++ references to some core objects
1648 pTextHelper->SetEditSource( ::std::unique_ptr<SvxEditSource>() );
1649 //! make TextHelper release references
1650 //! (e.g. the one set by the 'SetEventSource' call)
1651 pTextHelper->Dispose();
1652 delete pTextHelper; pTextHelper = 0;
1655 // XAccessible
1656 uno::Reference< XAccessibleContext > SAL_CALL SmEditAccessible::getAccessibleContext( )
1657 throw (RuntimeException, std::exception)
1659 SolarMutexGuard aGuard;
1660 return this;
1663 // XAccessibleComponent
1664 sal_Bool SAL_CALL SmEditAccessible::containsPoint( const awt::Point& aPoint )
1665 throw (RuntimeException, std::exception)
1667 //! the arguments coordinates are relativ to the current window !
1668 //! Thus the top left-point is (0, 0)
1670 SolarMutexGuard aGuard;
1671 if (!pWin)
1672 throw RuntimeException();
1674 Size aSz( pWin->GetSizePixel() );
1675 return aPoint.X >= 0 && aPoint.Y >= 0 &&
1676 aPoint.X < aSz.Width() && aPoint.Y < aSz.Height();
1679 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleAtPoint( const awt::Point& aPoint )
1680 throw (RuntimeException, std::exception)
1682 SolarMutexGuard aGuard;
1683 if (!pTextHelper)
1684 throw RuntimeException();
1685 return pTextHelper->GetAt( aPoint );
1688 awt::Rectangle SAL_CALL SmEditAccessible::getBounds( )
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 return lcl_GetBounds( pWin );
1699 awt::Point SAL_CALL SmEditAccessible::getLocation( )
1700 throw (RuntimeException, std::exception)
1702 SolarMutexGuard aGuard;
1703 if (!pWin)
1704 throw RuntimeException();
1705 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1706 "mismatch of window parent and accessible parent" );
1707 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1708 return awt::Point( aRect.X, aRect.Y );
1711 awt::Point SAL_CALL SmEditAccessible::getLocationOnScreen( )
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" );
1719 return lcl_GetLocationOnScreen( pWin );
1722 awt::Size SAL_CALL SmEditAccessible::getSize( )
1723 throw (RuntimeException, std::exception)
1725 SolarMutexGuard aGuard;
1726 if (!pWin)
1727 throw RuntimeException();
1728 OSL_ENSURE(pWin->GetParent()->GetAccessible() == getAccessibleParent(),
1729 "mismatch of window parent and accessible parent" );
1731 Size aSz( pWin->GetSizePixel() );
1732 #if OSL_DEBUG_LEVEL > 1
1733 awt::Rectangle aRect( lcl_GetBounds( pWin ) );
1734 Size aSz2( aRect.Width, aRect.Height );
1735 OSL_ENSURE( aSz == aSz2, "mismatch in width" );
1736 #endif
1737 return awt::Size( aSz.Width(), aSz.Height() );
1740 void SAL_CALL SmEditAccessible::grabFocus( )
1741 throw (RuntimeException, std::exception)
1743 SolarMutexGuard aGuard;
1744 if (!pWin)
1745 throw RuntimeException();
1747 pWin->GrabFocus();
1750 sal_Int32 SAL_CALL SmEditAccessible::getForeground()
1751 throw (RuntimeException, std::exception)
1753 SolarMutexGuard aGuard;
1755 if (!pWin)
1756 throw RuntimeException();
1757 return (sal_Int32) pWin->GetTextColor().GetColor();
1760 sal_Int32 SAL_CALL SmEditAccessible::getBackground()
1761 throw (RuntimeException, std::exception)
1763 SolarMutexGuard aGuard;
1765 if (!pWin)
1766 throw RuntimeException();
1767 Wallpaper aWall( pWin->GetDisplayBackground() );
1768 ColorData nCol;
1769 if (aWall.IsBitmap() || aWall.IsGradient())
1770 nCol = pWin->GetSettings().GetStyleSettings().GetWindowColor().GetColor();
1771 else
1772 nCol = aWall.GetColor().GetColor();
1773 return (sal_Int32) nCol;
1776 // XAccessibleContext
1777 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleChildCount( )
1778 throw (RuntimeException, std::exception)
1780 SolarMutexGuard aGuard;
1781 if (!pTextHelper)
1782 throw RuntimeException();
1783 return pTextHelper->GetChildCount();
1786 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleChild( sal_Int32 i )
1787 throw (IndexOutOfBoundsException, RuntimeException, std::exception)
1789 SolarMutexGuard aGuard;
1790 if (!pTextHelper)
1791 throw RuntimeException();
1792 return pTextHelper->GetChild( i );
1795 uno::Reference< XAccessible > SAL_CALL SmEditAccessible::getAccessibleParent( )
1796 throw (RuntimeException, std::exception)
1798 SolarMutexGuard aGuard;
1799 if (!pWin)
1800 throw RuntimeException();
1802 vcl::Window *pAccParent = pWin->GetAccessibleParentWindow();
1803 OSL_ENSURE( pAccParent, "accessible parent missing" );
1804 return pAccParent ? pAccParent->GetAccessible() : Reference< XAccessible >();
1807 sal_Int32 SAL_CALL SmEditAccessible::getAccessibleIndexInParent( )
1808 throw (RuntimeException, std::exception)
1810 SolarMutexGuard aGuard;
1811 sal_Int32 nIdx = -1;
1812 vcl::Window *pAccParent = pWin ? pWin->GetAccessibleParentWindow() : 0;
1813 if (pAccParent)
1815 sal_uInt16 nCnt = pAccParent->GetAccessibleChildWindowCount();
1816 for (sal_uInt16 i = 0; i < nCnt && nIdx == -1; ++i)
1817 if (pAccParent->GetAccessibleChildWindow( i ) == pWin)
1818 nIdx = i;
1820 return nIdx;
1823 sal_Int16 SAL_CALL SmEditAccessible::getAccessibleRole( )
1824 throw (RuntimeException, std::exception)
1826 SolarMutexGuard aGuard;
1827 return AccessibleRole::PANEL /*TEXT ?*/;
1830 OUString SAL_CALL SmEditAccessible::getAccessibleDescription( )
1831 throw (RuntimeException, std::exception)
1833 SolarMutexGuard aGuard;
1834 return OUString(); // empty as agreed with product-management
1837 OUString SAL_CALL SmEditAccessible::getAccessibleName( )
1838 throw (RuntimeException, std::exception)
1840 SolarMutexGuard aGuard;
1841 // same name as displayed by the window when not docked
1842 return aAccName;
1845 uno::Reference< XAccessibleRelationSet > SAL_CALL SmEditAccessible::getAccessibleRelationSet( )
1846 throw (RuntimeException, std::exception)
1848 SolarMutexGuard aGuard;
1849 Reference< XAccessibleRelationSet > xRelSet = new utl::AccessibleRelationSetHelper();
1850 return xRelSet; // empty relation set
1853 uno::Reference< XAccessibleStateSet > SAL_CALL SmEditAccessible::getAccessibleStateSet( )
1854 throw (RuntimeException, std::exception)
1856 SolarMutexGuard aGuard;
1857 ::utl::AccessibleStateSetHelper *pStateSet =
1858 new ::utl::AccessibleStateSetHelper;
1860 Reference<XAccessibleStateSet> xStateSet( pStateSet );
1862 if (!pWin || !pTextHelper)
1863 pStateSet->AddState( AccessibleStateType::DEFUNC );
1864 else
1866 pStateSet->AddState( AccessibleStateType::MULTI_LINE );
1867 pStateSet->AddState( AccessibleStateType::ENABLED );
1868 pStateSet->AddState( AccessibleStateType::FOCUSABLE );
1869 if (pWin->HasFocus())
1870 pStateSet->AddState( AccessibleStateType::FOCUSED );
1871 if (pWin->IsActive())
1872 pStateSet->AddState( AccessibleStateType::ACTIVE );
1873 if (pWin->IsVisible())
1874 pStateSet->AddState( AccessibleStateType::SHOWING );
1875 if (pWin->IsReallyVisible())
1876 pStateSet->AddState( AccessibleStateType::VISIBLE );
1877 if (COL_TRANSPARENT != pWin->GetBackground().GetColor().GetColor())
1878 pStateSet->AddState( AccessibleStateType::OPAQUE );
1881 return xStateSet;
1884 Locale SAL_CALL SmEditAccessible::getLocale( )
1885 throw (IllegalAccessibleComponentStateException, RuntimeException, std::exception)
1887 SolarMutexGuard aGuard;
1888 // should be the document language...
1889 // We use the language of the localized symbol names here.
1890 return Application::GetSettings().GetUILanguageTag().getLocale();
1894 // XAccessibleEventBroadcaster
1895 void SAL_CALL SmEditAccessible::addAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1896 throw (RuntimeException, std::exception)
1898 if (pTextHelper) // not disposing (about to destroy view shell)
1899 pTextHelper->AddEventListener( xListener );
1902 void SAL_CALL SmEditAccessible::removeAccessibleEventListener( const uno::Reference< XAccessibleEventListener >& xListener )
1903 throw (RuntimeException, std::exception)
1905 if (pTextHelper) // not disposing (about to destroy view shell)
1906 pTextHelper->RemoveEventListener( xListener );
1909 OUString SAL_CALL SmEditAccessible::getImplementationName()
1910 throw (RuntimeException, std::exception)
1912 return OUString("SmEditAccessible");
1915 sal_Bool SAL_CALL SmEditAccessible::supportsService(
1916 const OUString& rServiceName )
1917 throw (RuntimeException, std::exception)
1919 return cppu::supportsService(this, rServiceName);
1922 Sequence< OUString > SAL_CALL SmEditAccessible::getSupportedServiceNames()
1923 throw (RuntimeException, std::exception)
1925 return Sequence< OUString >{
1926 "com::sun::star::accessibility::Accessible",
1927 "com::sun::star::accessibility::AccessibleComponent",
1928 "com::sun::star::accessibility::AccessibleContext"
1934 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */