1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_accessibility.hxx"
26 #include <accessibility/standard/vclxaccessibletextcomponent.hxx>
27 #include <toolkit/helper/macros.hxx>
28 #include <toolkit/helper/convert.hxx>
29 #include <accessibility/helper/characterattributeshelper.hxx>
30 
31 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
32 #include <com/sun/star/datatransfer/clipboard/XClipboard.hpp>
33 #include <com/sun/star/datatransfer/clipboard/XFlushableClipboard.hpp>
34 #include <cppuhelper/typeprovider.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <vcl/window.hxx>
37 #include <vcl/svapp.hxx>
38 #include <vcl/unohelp2.hxx>
39 #include <vcl/ctrl.hxx>
40 
41 #include <memory>
42 #include <vector>
43 
44 using namespace ::com::sun::star;
45 using namespace ::com::sun::star::uno;
46 using namespace ::com::sun::star::lang;
47 using namespace ::com::sun::star::beans;
48 using namespace ::com::sun::star::accessibility;
49 using namespace ::comphelper;
50 
51 
52 //	----------------------------------------------------
53 //	class VCLXAccessibleTextComponent
54 //	----------------------------------------------------
55 
VCLXAccessibleTextComponent(VCLXWindow * pVCLXWindow)56 VCLXAccessibleTextComponent::VCLXAccessibleTextComponent( VCLXWindow* pVCLXWindow )
57 	:VCLXAccessibleComponent( pVCLXWindow )
58 {
59     if ( GetWindow() )
60 		m_sText = OutputDevice::GetNonMnemonicString( GetWindow()->GetText() );
61 }
62 
63 // -----------------------------------------------------------------------------
64 
~VCLXAccessibleTextComponent()65 VCLXAccessibleTextComponent::~VCLXAccessibleTextComponent()
66 {
67 }
68 
69 // -----------------------------------------------------------------------------
70 
SetText(const::rtl::OUString & sText)71 void VCLXAccessibleTextComponent::SetText( const ::rtl::OUString& sText )
72 {
73 	Any aOldValue, aNewValue;
74     if ( implInitTextChangedEvent( m_sText, sText, aOldValue, aNewValue ) )
75     {
76         m_sText = sText;
77 		NotifyAccessibleEvent( AccessibleEventId::TEXT_CHANGED, aOldValue, aNewValue );
78     }
79 }
80 
81 // -----------------------------------------------------------------------------
82 
ProcessWindowEvent(const VclWindowEvent & rVclWindowEvent)83 void VCLXAccessibleTextComponent::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent )
84 {
85     switch ( rVclWindowEvent.GetId() )
86     {
87         case VCLEVENT_WINDOW_FRAMETITLECHANGED:
88         {
89 			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
90             SetText( implGetText() );
91         }
92         break;
93 		default:
94 			VCLXAccessibleComponent::ProcessWindowEvent( rVclWindowEvent );
95    }
96 }
97 
98 // -----------------------------------------------------------------------------
99 // OCommonAccessibleText
100 // -----------------------------------------------------------------------------
101 
implGetText()102 ::rtl::OUString VCLXAccessibleTextComponent::implGetText()
103 {
104     ::rtl::OUString aText;
105     if ( GetWindow() )
106 		aText = OutputDevice::GetNonMnemonicString( GetWindow()->GetText() );
107 
108     return aText;
109 }
110 
111 // -----------------------------------------------------------------------------
112 
implGetLocale()113 lang::Locale VCLXAccessibleTextComponent::implGetLocale()
114 {
115 	return Application::GetSettings().GetLocale();
116 }
117 
118 // -----------------------------------------------------------------------------
119 
implGetSelection(sal_Int32 & nStartIndex,sal_Int32 & nEndIndex)120 void VCLXAccessibleTextComponent::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex )
121 {
122 	nStartIndex = 0;
123 	nEndIndex = 0;
124 }
125 
126 // -----------------------------------------------------------------------------
127 // XComponent
128 // -----------------------------------------------------------------------------
129 
disposing()130 void VCLXAccessibleTextComponent::disposing()
131 {
132 	VCLXAccessibleComponent::disposing();
133 
134 	m_sText = ::rtl::OUString();
135 }
136 
137 // -----------------------------------------------------------------------------
138 // XInterface
139 // -----------------------------------------------------------------------------
140 
IMPLEMENT_FORWARD_XINTERFACE2(VCLXAccessibleTextComponent,VCLXAccessibleComponent,VCLXAccessibleTextComponent_BASE)141 IMPLEMENT_FORWARD_XINTERFACE2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
142 
143 // -----------------------------------------------------------------------------
144 // XTypeProvider
145 // -----------------------------------------------------------------------------
146 
147 IMPLEMENT_FORWARD_XTYPEPROVIDER2( VCLXAccessibleTextComponent, VCLXAccessibleComponent, VCLXAccessibleTextComponent_BASE )
148 
149 // -----------------------------------------------------------------------------
150 // XAccessibleText
151 // -----------------------------------------------------------------------------
152 
153 sal_Int32 VCLXAccessibleTextComponent::getCaretPosition() throw (RuntimeException)
154 {
155 	OExternalLockGuard aGuard( this );
156 
157 	return -1;
158 }
159 
160 // -----------------------------------------------------------------------------
161 
setCaretPosition(sal_Int32 nIndex)162 sal_Bool VCLXAccessibleTextComponent::setCaretPosition( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
163 {
164 	OExternalLockGuard aGuard( this );
165 
166 	return setSelection( nIndex, nIndex );
167 }
168 
169 // -----------------------------------------------------------------------------
170 
getCharacter(sal_Int32 nIndex)171 sal_Unicode VCLXAccessibleTextComponent::getCharacter( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
172 {
173 	OExternalLockGuard aGuard( this );
174 
175 	return OCommonAccessibleText::getCharacter( nIndex );
176 }
177 
178 // -----------------------------------------------------------------------------
179 
getCharacterAttributes(sal_Int32 nIndex,const Sequence<::rtl::OUString> & aRequestedAttributes)180 Sequence< PropertyValue > VCLXAccessibleTextComponent::getCharacterAttributes( sal_Int32 nIndex, const Sequence< ::rtl::OUString >& aRequestedAttributes ) throw (IndexOutOfBoundsException, RuntimeException)
181 {
182 	OExternalLockGuard aGuard( this );
183 
184 	Sequence< PropertyValue > aValues;
185 	::rtl::OUString sText( implGetText() );
186 
187     if ( !implIsValidIndex( nIndex, sText.getLength() ) )
188         throw IndexOutOfBoundsException();
189 
190     if ( GetWindow() )
191     {
192 		Font aFont = GetWindow()->GetControlFont();
193 
194 		sal_Int32 nBackColor = GetWindow()->GetControlBackground().GetColor();
195 		sal_Int32 nColor = GetWindow()->GetControlForeground().GetColor();
196 
197 		// MT: Code with default font was introduced with the IA2 CWS, but I am not convinced that this is the correct font...
198 		// Decide what to do when we have a concrete issue.
199 		/*
200 		Font aDefaultVCLFont;
201 		OutputDevice* pDev = Application::GetDefaultDevice();
202 		if ( pDev )
203 		{
204 			aDefaultVCLFont = pDev->GetSettings().GetStyleSettings().GetAppFont();
205 			if ( !aFont.GetName().Len() )
206 			{
207 				String aDefaultName = aDefaultVCLFont.GetName();
208 				aFont.SetName( aDefaultName );
209 			}
210 			if ( !aFont.GetHeight() )
211 			{
212 				aFont.SetHeight( aDefaultVCLFont.GetHeight() );
213 			}
214 			if ( aFont.GetWeight() == WEIGHT_DONTKNOW )
215 			{
216 				aFont.SetWeight( aDefaultVCLFont.GetWeight() );
217 			}
218 
219 			//if nColor is -1, it may indicate that the default color black is using.
220 			if ( nColor == -1)
221 			{
222 				nColor = aDefaultVCLFont.GetColor().GetColor();
223 			}
224 		}
225 		*/
226 
227 		// MT: Adjustment stuff was introduced with the IA2 CWS, but adjustment is not a character attribute...
228 		// In case we reintroduce it, use adjustment as extra parameter for the CharacterAttributesHelper...
229 		/*
230 		WinBits aBits = GetWindow()->GetStyle();
231 		sal_Int16 nAdjust = -1;
232 		if ( aBits & WB_LEFT )
233 		{
234 			nAdjust = style::ParagraphAdjust_LEFT;
235 		}
236 		else if ( aBits & WB_RIGHT )
237 		{
238 			nAdjust = style::ParagraphAdjust_RIGHT;
239 		}
240 		else if ( aBits & WB_CENTER )
241 		{
242 			nAdjust = style::ParagraphAdjust_CENTER;
243 		}
244 		*/
245 
246 		::std::auto_ptr< CharacterAttributesHelper > pHelper( new CharacterAttributesHelper( aFont, nBackColor, nColor ) );
247 
248 		aValues = pHelper->GetCharacterAttributes( aRequestedAttributes );
249     }
250 
251     return aValues;
252 }
253 
254 // -----------------------------------------------------------------------------
255 
getCharacterBounds(sal_Int32 nIndex)256 awt::Rectangle VCLXAccessibleTextComponent::getCharacterBounds( sal_Int32 nIndex ) throw (IndexOutOfBoundsException, RuntimeException)
257 {
258 	OExternalLockGuard aGuard( this );
259 
260     if ( !implIsValidIndex( nIndex, implGetText().getLength() ) )
261         throw IndexOutOfBoundsException();
262 
263 	awt::Rectangle aRect;
264 	Control* pControl = static_cast< Control* >( GetWindow() );
265 	if ( pControl )
266 		aRect = AWTRectangle( pControl->GetCharacterBounds( nIndex ) );
267 
268     return aRect;
269 }
270 
271 // -----------------------------------------------------------------------------
272 
getCharacterCount()273 sal_Int32 VCLXAccessibleTextComponent::getCharacterCount() throw (RuntimeException)
274 {
275 	OExternalLockGuard aGuard( this );
276 
277 	return OCommonAccessibleText::getCharacterCount();
278 }
279 
280 // -----------------------------------------------------------------------------
281 
getIndexAtPoint(const awt::Point & aPoint)282 sal_Int32 VCLXAccessibleTextComponent::getIndexAtPoint( const awt::Point& aPoint ) throw (RuntimeException)
283 {
284 	OExternalLockGuard aGuard( this );
285 
286 	sal_Int32 nIndex = -1;
287 	Control* pControl = static_cast< Control* >( GetWindow() );
288 	if ( pControl )
289 		nIndex = pControl->GetIndexForPoint( VCLPoint( aPoint ) );
290 
291     return nIndex;
292 }
293 
294 // -----------------------------------------------------------------------------
295 
getSelectedText()296 ::rtl::OUString VCLXAccessibleTextComponent::getSelectedText() throw (RuntimeException)
297 {
298 	OExternalLockGuard aGuard( this );
299 
300 	return OCommonAccessibleText::getSelectedText();
301 }
302 
303 // -----------------------------------------------------------------------------
304 
getSelectionStart()305 sal_Int32 VCLXAccessibleTextComponent::getSelectionStart() throw (RuntimeException)
306 {
307 	OExternalLockGuard aGuard( this );
308 
309 	return OCommonAccessibleText::getSelectionStart();
310 }
311 
312 // -----------------------------------------------------------------------------
313 
getSelectionEnd()314 sal_Int32 VCLXAccessibleTextComponent::getSelectionEnd() throw (RuntimeException)
315 {
316 	OExternalLockGuard aGuard( this );
317 
318 	return OCommonAccessibleText::getSelectionEnd();
319 }
320 
321 // -----------------------------------------------------------------------------
322 
setSelection(sal_Int32 nStartIndex,sal_Int32 nEndIndex)323 sal_Bool VCLXAccessibleTextComponent::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
324 {
325 	OExternalLockGuard aGuard( this );
326 
327     if ( !implIsValidRange( nStartIndex, nEndIndex, implGetText().getLength() ) )
328         throw IndexOutOfBoundsException();
329 
330 	return sal_False;
331 }
332 
333 // -----------------------------------------------------------------------------
334 
getText()335 ::rtl::OUString VCLXAccessibleTextComponent::getText() throw (RuntimeException)
336 {
337 	OExternalLockGuard aGuard( this );
338 
339 	return OCommonAccessibleText::getText();
340 }
341 
342 // -----------------------------------------------------------------------------
343 
getTextRange(sal_Int32 nStartIndex,sal_Int32 nEndIndex)344 ::rtl::OUString VCLXAccessibleTextComponent::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
345 {
346 	OExternalLockGuard aGuard( this );
347 
348 	return OCommonAccessibleText::getTextRange( nStartIndex, nEndIndex );
349 }
350 
351 // -----------------------------------------------------------------------------
352 
getTextAtIndex(sal_Int32 nIndex,sal_Int16 aTextType)353 ::com::sun::star::accessibility::TextSegment VCLXAccessibleTextComponent::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
354 {
355 	OExternalLockGuard aGuard( this );
356 
357 	return OCommonAccessibleText::getTextAtIndex( nIndex, aTextType );
358 }
359 
360 // -----------------------------------------------------------------------------
361 
getTextBeforeIndex(sal_Int32 nIndex,sal_Int16 aTextType)362 ::com::sun::star::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
363 {
364 	OExternalLockGuard aGuard( this );
365 
366 	return OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType );
367 }
368 
369 // -----------------------------------------------------------------------------
370 
getTextBehindIndex(sal_Int32 nIndex,sal_Int16 aTextType)371 ::com::sun::star::accessibility::TextSegment VCLXAccessibleTextComponent::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException)
372 {
373 	OExternalLockGuard aGuard( this );
374 
375 	return OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType );
376 }
377 
378 // -----------------------------------------------------------------------------
379 
copyText(sal_Int32 nStartIndex,sal_Int32 nEndIndex)380 sal_Bool VCLXAccessibleTextComponent::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) throw (IndexOutOfBoundsException, RuntimeException)
381 {
382 	OExternalLockGuard aGuard( this );
383 
384 	sal_Bool bReturn = sal_False;
385 
386 	if ( GetWindow() )
387 	{
388 		Reference< datatransfer::clipboard::XClipboard > xClipboard = GetWindow()->GetClipboard();
389 		if ( xClipboard.is() )
390 		{
391 			::rtl::OUString sText( getTextRange( nStartIndex, nEndIndex ) );
392 
393 			::vcl::unohelper::TextDataObject* pDataObj = new ::vcl::unohelper::TextDataObject( sText );
394 			const sal_uInt32 nRef = Application::ReleaseSolarMutex();
395 			xClipboard->setContents( pDataObj, NULL );
396 
397 			Reference< datatransfer::clipboard::XFlushableClipboard > xFlushableClipboard( xClipboard, uno::UNO_QUERY );
398 			if( xFlushableClipboard.is() )
399 				xFlushableClipboard->flushClipboard();
400 
401 			Application::AcquireSolarMutex( nRef );
402 
403 			bReturn = sal_True;
404 		}
405 	}
406 
407     return bReturn;
408 }
409 
410 // -----------------------------------------------------------------------------
411