1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_EDITENG_ACCESSIBLEEDITABLETEXTPARA_HXX
21 #define INCLUDED_EDITENG_ACCESSIBLEEDITABLETEXTPARA_HXX
22 
23 #include <config_options.h>
24 #include <rtl/ustring.hxx>
25 #include <tools/gen.hxx>
26 #include <cppuhelper/compbase.hxx>
27 #include <cppuhelper/basemutex.hxx>
28 
29 #include <com/sun/star/uno/Reference.hxx>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
31 #include <com/sun/star/accessibility/AccessibleScrollType.hpp>
32 #include <com/sun/star/accessibility/XAccessible.hpp>
33 #include <com/sun/star/accessibility/XAccessibleContext.hpp>
34 #include <com/sun/star/accessibility/XAccessibleComponent.hpp>
35 #include <com/sun/star/accessibility/XAccessibleEditableText.hpp>
36 #include <com/sun/star/accessibility/XAccessibleTextAttributes.hpp>
37 #include <com/sun/star/accessibility/XAccessibleHypertext.hpp>
38 #include <com/sun/star/accessibility/XAccessibleMultiLineText.hpp>
39 #include <com/sun/star/accessibility/XAccessibleEventBroadcaster.hpp>
40 
41 #include <comphelper/accessibletexthelper.hxx>
42 #include <editeng/AccessibleParaManager.hxx>
43 #include <editeng/editdata.hxx>
44 #include <editeng/editengdllapi.h>
45 
46 class SvxViewForwarder;
47 class MapMode;
48 class SvxAccessibleTextAdapter;
49 class SvxAccessibleTextEditViewAdapter;
50 namespace accessibility { class AccessibleImageBullet; }
51 
52 namespace accessibility
53 {
54     typedef ::cppu::WeakComponentImplHelper< css::accessibility::XAccessible,
55                                      css::accessibility::XAccessibleContext,
56                                      css::accessibility::XAccessibleComponent,
57                                      css::accessibility::XAccessibleEditableText,
58                                      css::accessibility::XAccessibleEventBroadcaster,
59                                      css::accessibility::XAccessibleTextAttributes,
60                                      css::accessibility::XAccessibleHypertext,
61                                      css::accessibility::XAccessibleMultiLineText,
62                                      css::lang::XServiceInfo >  AccessibleTextParaInterfaceBase;
63 
64     /** This class implements the actual text paragraphs for the EditEngine/Outliner UAA
65      */
66     class UNLESS_MERGELIBS(EDITENG_DLLPUBLIC) AccessibleEditableTextPara final : public ::cppu::BaseMutex, public AccessibleTextParaInterfaceBase, private ::comphelper::OCommonAccessibleText
67     {
68 
69         // override OCommonAccessibleText methods
70         virtual OUString                 implGetText() override;
71         virtual css::lang::Locale        implGetLocale() override;
72         virtual void                     implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) override;
73         virtual void                     implGetParagraphBoundary( const OUString& rtext, css::i18n::Boundary& rBoundary, sal_Int32 nIndex ) override;
74         virtual void                     implGetLineBoundary( const OUString& rtext, css::i18n::Boundary& rBoundary, sal_Int32 nIndex ) override;
75 
76     public:
77         /// Create accessible object for given parent
78         // #i27138#
79         // - add parameter <_pParaManager> (default value NULL)
80         //   This has to be the instance of <AccessibleParaManager>, which
81         //   created and manages this accessible paragraph.
82         AccessibleEditableTextPara ( const css::uno::Reference< css::accessibility::XAccessible >& rParent,
83                                      const AccessibleParaManager* _pParaManager = nullptr );
84 
85         virtual ~AccessibleEditableTextPara () override;
86 
87         // XInterface
88         virtual css::uno::Any SAL_CALL queryInterface (const css::uno::Type & rType) override;
89 
90         // XAccessible
91         virtual css::uno::Reference< css::accessibility::XAccessibleContext > SAL_CALL getAccessibleContext(  ) override;
92 
93         // XAccessibleContext
94         virtual sal_Int32 SAL_CALL getAccessibleChildCount() override;
95         virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleChild( sal_Int32 i ) override;
96         virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleParent() override;
97         virtual sal_Int32 SAL_CALL getAccessibleIndexInParent() override;
98         virtual sal_Int16 SAL_CALL getAccessibleRole() override;
99         /// Maximal length of text returned by getAccessibleDescription()
100         enum { MaxDescriptionLen = 40 };
101         virtual OUString SAL_CALL getAccessibleDescription() override;
102         virtual OUString SAL_CALL getAccessibleName() override;
103         virtual css::uno::Reference< css::accessibility::XAccessibleRelationSet > SAL_CALL getAccessibleRelationSet() override;
104         virtual css::uno::Reference< css::accessibility::XAccessibleStateSet > SAL_CALL getAccessibleStateSet() override;
105         virtual css::lang::Locale SAL_CALL getLocale() override;
106 
107         // XAccessibleEventBroadcaster
108         virtual void SAL_CALL addAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
109         virtual void SAL_CALL removeAccessibleEventListener( const css::uno::Reference< css::accessibility::XAccessibleEventListener >& xListener ) override;
110 
111         // XAccessibleComponent
112         virtual sal_Bool SAL_CALL containsPoint( const css::awt::Point& aPoint ) override;
113         virtual css::uno::Reference< css::accessibility::XAccessible > SAL_CALL getAccessibleAtPoint( const css::awt::Point& aPoint ) override;
114         virtual css::awt::Rectangle SAL_CALL getBounds(  ) override;
115         virtual css::awt::Point SAL_CALL getLocation(  ) override;
116         virtual css::awt::Point SAL_CALL getLocationOnScreen(  ) override;
117         virtual css::awt::Size SAL_CALL getSize(  ) override;
118         virtual void SAL_CALL grabFocus(  ) override;
119         virtual sal_Int32 SAL_CALL getForeground(  ) override;
120         virtual sal_Int32 SAL_CALL getBackground(  ) override;
121 
122         // XAccessibleText (this comes implicitly inherited by XAccessibleEditableText AND by XAccessibleMultiLineText)
123         virtual sal_Int32 SAL_CALL getCaretPosition() override;
124         virtual sal_Bool SAL_CALL setCaretPosition( sal_Int32 nIndex ) override;
125         virtual sal_Unicode SAL_CALL getCharacter( sal_Int32 nIndex ) override;
126         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& aRequestedAttributes ) override;
127         virtual css::awt::Rectangle SAL_CALL getCharacterBounds( sal_Int32 nIndex ) override;
128         virtual sal_Int32 SAL_CALL getCharacterCount() override;
129         virtual sal_Int32 SAL_CALL getIndexAtPoint( const css::awt::Point& aPoint ) override;
130         virtual OUString SAL_CALL getSelectedText() override;
131         virtual sal_Int32 SAL_CALL getSelectionStart() override;
132         virtual sal_Int32 SAL_CALL getSelectionEnd() override;
133         virtual sal_Bool SAL_CALL setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
134         virtual OUString SAL_CALL getText() override;
135         virtual OUString SAL_CALL getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
136         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
137         virtual css::accessibility::TextSegment SAL_CALL getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
138         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
139         virtual css::accessibility::TextSegment SAL_CALL getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
140         /// Does not support AccessibleTextType::SENTENCE (missing feature in EditEngine)
141         virtual css::accessibility::TextSegment SAL_CALL getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) override;
142         virtual sal_Bool SAL_CALL copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
143         virtual sal_Bool SAL_CALL scrollSubstringTo( sal_Int32 nStartIndex, sal_Int32 nEndIndex, css::accessibility::AccessibleScrollType aScrollType) override;
144 
145         // XAccessibleEditableText
146         virtual sal_Bool SAL_CALL cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
147         virtual sal_Bool SAL_CALL pasteText( sal_Int32 nIndex ) override;
148         virtual sal_Bool SAL_CALL deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) override;
149         virtual sal_Bool SAL_CALL insertText( const OUString& sText, sal_Int32 nIndex ) override;
150         virtual sal_Bool SAL_CALL replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement ) override;
151         virtual sal_Bool SAL_CALL setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const css::uno::Sequence< css::beans::PropertyValue >& aAttributeSet ) override;
152         virtual sal_Bool SAL_CALL setText( const OUString& sText ) override;
153 
154         // XAccessibleTextAttributes
155         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getDefaultAttributes( const css::uno::Sequence< OUString >& RequestedAttributes ) override;
156         virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL getRunAttributes( ::sal_Int32 Index, const css::uno::Sequence< OUString >& RequestedAttributes ) override;
157 
158         // XAccessibleHypertext
159         virtual ::sal_Int32 SAL_CALL getHyperLinkCount(  ) override;
160         virtual css::uno::Reference< css::accessibility::XAccessibleHyperlink > SAL_CALL getHyperLink( ::sal_Int32 nLinkIndex ) override;
161         virtual ::sal_Int32 SAL_CALL getHyperLinkIndex( ::sal_Int32 nCharIndex ) override;
162 
163         // XAccessibleMultiLineText
164         virtual ::sal_Int32 SAL_CALL getLineNumberAtIndex( ::sal_Int32 nIndex ) override;
165         virtual css::accessibility::TextSegment SAL_CALL getTextAtLineNumber( ::sal_Int32 nLineNo ) override;
166         virtual css::accessibility::TextSegment SAL_CALL getTextAtLineWithCaret(  ) override;
167         virtual ::sal_Int32 SAL_CALL getNumberOfLineWithCaret(  ) override;
168 
169         // XServiceInfo
170         virtual OUString SAL_CALL getImplementationName() override;
171         virtual sal_Bool SAL_CALL supportsService (const OUString& sServiceName) override;
172         virtual css::uno::Sequence< OUString> SAL_CALL getSupportedServiceNames() override;
173 
174         /** Set the current index in the accessibility parent
175 
176             @attention This method does not lock the SolarMutex,
177             leaving that to the calling code. This is because only
178             there potential deadlock situations can be resolved. Thus,
179             make sure SolarMutex is locked when calling this.
180          */
181         void SetIndexInParent( sal_Int32 nIndex );
182 
183         /** Get the current index in the accessibility parent
184 
185             @attention This method does not lock the SolarMutex,
186             leaving that to the calling code. This is because only
187             there potential deadlock situations can be resolved. Thus,
188             make sure SolarMutex is locked when calling this.
189          */
190         sal_Int32 GetIndexInParent() const { return mnIndexInParent; }
191 
192         /** Set the current paragraph number
193 
194             @attention This method does not lock the SolarMutex,
195             leaving that to the calling code. This is because only
196             there potential deadlock situations can be resolved. Thus,
197             make sure SolarMutex is locked when calling this.
198          */
199         void SetParagraphIndex( sal_Int32 nIndex );
200 
201         /** Query the current paragraph number (0 - nParas-1)
202 
203             @attention This method does not lock the SolarMutex,
204             leaving that to the calling code. This is because only
205             there potential deadlock situations can be resolved. Thus,
206             make sure SolarMutex is locked when calling this.
207          */
208         sal_Int32 GetParagraphIndex() const { return mnParagraphIndex; }
209 
210         /** Set the edit engine offset
211 
212             @attention This method does not lock the SolarMutex,
213             leaving that to the calling code. This is because only
214             there potential deadlock situations can be resolved. Thus,
215             make sure SolarMutex is locked when calling this.
216          */
217         void SetEEOffset( const Point& rOffset );
218 
219         /** Set the EditEngine offset
220 
221             @attention This method does not lock the SolarMutex,
222             leaving that to the calling code. This is because only
223             there potential deadlock situations can be resolved. Thus,
224             make sure SolarMutex is locked when calling this.
225          */
226         void SetEditSource( SvxEditSourceAdapter* pEditSource );
227 
228         /** Dispose this object
229 
230             Notifies and deregisters the listeners, drops all references.
231          */
232         void Dispose();
233 
234         /// Calls all Listener objects to tell them the change. Don't hold locks when calling this!
235         void FireEvent(const sal_Int16 nEventId, const css::uno::Any& rNewValue = css::uno::Any(), const css::uno::Any& rOldValue = css::uno::Any() ) const;
236 
237         /// Sets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this!
238         void SetState( const sal_Int16 nStateId );
239         /// Unsets the given state on the internal state set and fires STATE_CHANGE event. Don't hold locks when calling this!
240         void UnSetState( const sal_Int16 nStateId );
241 
242         static tools::Rectangle LogicToPixel( const tools::Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder const & rForwarder );
243 
244         SvxEditSourceAdapter& GetEditSource() const;
245 
246         /** Query the SvxTextForwarder for EditEngine access.
247 
248             @attention This method does not lock the SolarMutex,
249             leaving that to the calling code. This is because only
250             there potential deadlock situations can be resolved. Thus,
251             make sure SolarMutex is locked when calling this.
252          */
253         SvxAccessibleTextAdapter&   GetTextForwarder() const;
254 
255         /** Query the SvxViewForwarder for EditEngine access.
256 
257             @attention This method does not lock the SolarMutex,
258             leaving that to the calling code. This is because only
259             there potential deadlock situations can be resolved. Thus,
260             make sure SolarMutex is locked when calling this.
261          */
262         SvxViewForwarder&   GetViewForwarder() const;
263 
264         /** Query whether a GetEditViewForwarder( sal_False ) will return a forwarder
265 
266             @attention This method does not lock the SolarMutex,
267             leaving that to the calling code. This is because only
268             there potential deadlock situations can be resolved. Thus,
269             make sure SolarMutex is locked when calling this.
270          */
271         bool    HaveEditView() const;
272 
273         /** Query the SvxEditViewForwarder for EditEngine access.
274 
275             @attention This method does not lock the SolarMutex,
276             leaving that to the calling code. This is because only
277             there potential deadlock situations can be resolved. Thus,
278             make sure SolarMutex is locked when calling this.
279          */
280         SvxAccessibleTextEditViewAdapter& GetEditViewForwarder( bool bCreate = false ) const;
281 
282         /** Send a TEXT_CHANGED event for this paragraph
283 
284             This method internally caters for calculating text
285             differences, and sends the appropriate Anys in the
286             Accessibility::TEXT_CHANGED event
287          */
288         void TextChanged();
289 
290     private:
291         AccessibleEditableTextPara( const AccessibleEditableTextPara& ) = delete;
292         AccessibleEditableTextPara& operator= ( const AccessibleEditableTextPara& ) = delete;
293 
294         /** Calculate character range of similar attributes
295 
296             @param nStartIndex
297             Therein, the start of the character range with the same attributes is returned
298 
299             @param nEndIndex
300             Therein, the end (exclusively) of the character range with the same attributes is returned
301 
302             @param nIndex
303             The character index at where to look for similar character attributes
304 
305             @return false, if the method was not able to determine the range
306          */
307         bool GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nIndex );
308 
309         int getNotifierClientId() const { return mnNotifierClientId; }
310 
311         /// Do we have children? This is the case for image bullets
312         bool HaveChildren();
313 
314         const Point& GetEEOffset() const { return maEEOffset; }
315 
316         // Get text from forwarder
317         OUString GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex );
318         sal_Int32 GetTextLen() const;
319 
320         /** Get the current selection of this paragraph
321 
322             @return sal_False, if nothing in this paragraph is selected
323          */
324         bool GetSelection(sal_Int32& nStartPos, sal_Int32& nEndPos );
325 
326         /** create selection from Accessible selection.
327 
328         */
329         ESelection  MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex );
330         ESelection  MakeSelection( sal_Int32 nEEIndex );
331         ESelection  MakeCursor( sal_Int32 nEEIndex );
332 
333         // check whether index value is within permitted range
334 
335         /// Check whether 0<=nIndex<=n-1
336         void CheckIndex( sal_Int32 nIndex );
337         /// Check whether 0<=nIndex<=n
338         void CheckPosition( sal_Int32 nIndex );
339         /// Check whether 0<=nStart<=n and 0<=nEnd<=n
340         void CheckRange( sal_Int32 nStart, sal_Int32 nEnd );
341 
342         void _correctValues( css::uno::Sequence< css::beans::PropertyValue >& rValues );
343         sal_Int32 SkipField(sal_Int32 nIndex, bool bForward);
344         // get overlapped field, extend return string. Only extend forward for now
345         void ExtendByField( css::accessibility::TextSegment& Segment );
346         OUString GetFieldTypeNameAtIndex(sal_Int32 nIndex);
347         // the paragraph index in the edit engine (guarded by solar mutex)
348         sal_Int32   mnParagraphIndex;
349 
350         // our current index in the parent (guarded by solar mutex)
351         sal_Int32   mnIndexInParent;
352 
353         // the current edit source (guarded by solar mutex)
354         SvxEditSourceAdapter* mpEditSource;
355 
356         // the possible child (for image bullets, guarded by solar mutex)
357         typedef WeakCppRef < css::accessibility::XAccessible, AccessibleImageBullet > WeakBullet;
358         WeakBullet maImageBullet;
359 
360         // the last string used for an Accessibility::TEXT_CHANGED event (guarded by solar mutex)
361         OUString maLastTextString;
362 
363         // the offset of the underlying EditEngine from the shape/cell (guarded by solar mutex)
364         Point maEEOffset;
365 
366         // the current state set (updated from SetState/UnSetState and guarded by solar mutex)
367         css::uno::Reference< css::accessibility::XAccessibleStateSet > mxStateSet;
368 
369         /// The shape we're the accessible for (unguarded)
370         css::uno::Reference< css::accessibility::XAccessible > mxParent;
371 
372         /// Our listeners (guarded by maMutex)
373         int mnNotifierClientId;
374 private:
375         // Text paragraphs should provide FLOWS_TO and FLOWS_FROM relations (#i27138#)
376         // the paragraph manager, which created this instance - is NULL, if
377         // instance isn't created by AccessibleParaManager.
378         // Needed for method <getAccessibleRelationSet()> to retrieve predecessor
379         // paragraph and the successor paragraph.
380         const AccessibleParaManager* mpParaManager;
381     };
382 
383 } // end of namespace accessibility
384 
385 #endif
386 
387 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
388