/src/libreoffice/editeng/source/accessibility/AccessibleEditableTextPara.cxx
Line | Count | Source |
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 | | |
21 | | // Global header |
22 | | |
23 | | |
24 | | #include <algorithm> |
25 | | #include <utility> |
26 | | #include <vcl/svapp.hxx> |
27 | | #include <tools/debug.hxx> |
28 | | #include <comphelper/diagnose_ex.hxx> |
29 | | #include <sal/log.hxx> |
30 | | #include <editeng/flditem.hxx> |
31 | | #include <com/sun/star/uno/Any.hxx> |
32 | | #include <com/sun/star/uno/Reference.hxx> |
33 | | #include <com/sun/star/awt/Point.hpp> |
34 | | #include <com/sun/star/awt/Rectangle.hpp> |
35 | | #include <com/sun/star/container/XNameContainer.hpp> |
36 | | #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> |
37 | | #include <com/sun/star/i18n/Boundary.hpp> |
38 | | #include <com/sun/star/accessibility/AccessibleRole.hpp> |
39 | | #include <com/sun/star/accessibility/AccessibleTextType.hpp> |
40 | | #include <com/sun/star/accessibility/AccessibleStateType.hpp> |
41 | | #include <com/sun/star/accessibility/AccessibleEventId.hpp> |
42 | | #include <comphelper/sequenceashashmap.hxx> |
43 | | #include <unotools/accessiblerelationsethelper.hxx> |
44 | | #include <com/sun/star/accessibility/AccessibleRelationType.hpp> |
45 | | #include <vcl/settings.hxx> |
46 | | #include <i18nlangtag/languagetag.hxx> |
47 | | |
48 | | #include <editeng/AccessibleParaManager.hxx> |
49 | | #include <editeng/editeng.hxx> |
50 | | #include <editeng/unoprnms.hxx> |
51 | | #include <editeng/unoipset.hxx> |
52 | | #include <editeng/outliner.hxx> |
53 | | #include <editeng/unoedprx.hxx> |
54 | | #include <editeng/unoedsrc.hxx> |
55 | | #include <svl/eitem.hxx> |
56 | | |
57 | | |
58 | | // Project-local header |
59 | | |
60 | | |
61 | | #include <com/sun/star/beans/PropertyState.hpp> |
62 | | |
63 | | #include <unopracc.hxx> |
64 | | #include <editeng/AccessibleEditableTextPara.hxx> |
65 | | #include "AccessibleHyperlink.hxx" |
66 | | #include "AccessibleImageBullet.hxx" |
67 | | |
68 | | #include <svtools/colorcfg.hxx> |
69 | | #include <editeng/numitem.hxx> |
70 | | #include <memory> |
71 | | |
72 | | using namespace ::com::sun::star; |
73 | | using namespace ::com::sun::star::beans; |
74 | | using namespace ::com::sun::star::accessibility; |
75 | | |
76 | | |
77 | | // AccessibleEditableTextPara implementation |
78 | | |
79 | | |
80 | | namespace accessibility |
81 | | { |
82 | | |
83 | | static const SvxItemPropertySet* ImplGetSvxCharAndParaPropertiesSet() |
84 | 0 | { |
85 | | // PropertyMap for character and paragraph properties |
86 | 0 | static const SfxItemPropertyMapEntry aPropMap[] = |
87 | 0 | { |
88 | 0 | SVX_UNOEDIT_OUTLINER_PROPERTIES, |
89 | 0 | SVX_UNOEDIT_CHAR_PROPERTIES, |
90 | 0 | SVX_UNOEDIT_PARA_PROPERTIES, |
91 | 0 | SVX_UNOEDIT_NUMBERING_PROPERTY, |
92 | 0 | { u"TextUserDefinedAttributes"_ustr, EE_CHAR_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, |
93 | 0 | { u"ParaUserDefinedAttributes"_ustr, EE_PARA_XMLATTRIBS, cppu::UnoType<css::container::XNameContainer>::get(), 0, 0}, |
94 | 0 | }; |
95 | 0 | static SvxItemPropertySet aPropSet( aPropMap, EditEngine::GetGlobalItemPool() ); |
96 | 0 | return &aPropSet; |
97 | 0 | } |
98 | | |
99 | | // #i27138# - add parameter <_pParaManager> |
100 | | AccessibleEditableTextPara::AccessibleEditableTextPara( |
101 | | const rtl::Reference<comphelper::OAccessible>& rpParent, |
102 | | const AccessibleParaManager* _pParaManager) |
103 | 0 | : mnParagraphIndex( 0 ), |
104 | 0 | mnIndexInParent( 0 ), |
105 | 0 | mpEditSource( nullptr ), |
106 | 0 | maEEOffset( 0, 0 ), |
107 | 0 | mpParent(rpParent), |
108 | 0 | mpParaManager( _pParaManager ) |
109 | 0 | { |
110 | | |
111 | | // Create the state set. |
112 | 0 | mnStateSet = 0; |
113 | | |
114 | | // these are always on |
115 | 0 | mnStateSet |= AccessibleStateType::MULTI_LINE; |
116 | 0 | mnStateSet |= AccessibleStateType::FOCUSABLE; |
117 | 0 | mnStateSet |= AccessibleStateType::VISIBLE; |
118 | 0 | mnStateSet |= AccessibleStateType::SHOWING; |
119 | 0 | mnStateSet |= AccessibleStateType::ENABLED; |
120 | 0 | mnStateSet |= AccessibleStateType::SENSITIVE; |
121 | 0 | } |
122 | | |
123 | | OUString AccessibleEditableTextPara::implGetText() |
124 | 0 | { |
125 | 0 | return GetTextRange( 0, GetTextLen() ); |
126 | 0 | } |
127 | | |
128 | | css::lang::Locale AccessibleEditableTextPara::implGetLocale() |
129 | 0 | { |
130 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
131 | 0 | "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); |
132 | | |
133 | | // return locale of first character in the paragraph |
134 | 0 | return LanguageTag(GetTextForwarder().GetLanguage( GetParagraphIndex(), 0 )).getLocale(); |
135 | 0 | } |
136 | | |
137 | | void AccessibleEditableTextPara::implGetSelection( sal_Int32& nStartIndex, sal_Int32& nEndIndex ) |
138 | 0 | { |
139 | 0 | sal_Int32 nStart, nEnd; |
140 | |
|
141 | 0 | if( GetSelection( nStart, nEnd ) ) |
142 | 0 | { |
143 | 0 | nStartIndex = nStart; |
144 | 0 | nEndIndex = nEnd; |
145 | 0 | } |
146 | 0 | else |
147 | 0 | { |
148 | | // #102234# No exception, just set to 'invalid' |
149 | 0 | nStartIndex = -1; |
150 | 0 | nEndIndex = -1; |
151 | 0 | } |
152 | 0 | } |
153 | | |
154 | | void AccessibleEditableTextPara::implGetParagraphBoundary( const OUString& rText, css::i18n::Boundary& rBoundary, sal_Int32 /*nIndex*/ ) |
155 | 0 | { |
156 | 0 | SAL_INFO( "editeng", "AccessibleEditableTextPara::implGetParagraphBoundary: only a base implementation, ignoring the index" ); |
157 | | |
158 | 0 | rBoundary.startPos = 0; |
159 | 0 | rBoundary.endPos = rText.getLength(); |
160 | 0 | } |
161 | | |
162 | | void AccessibleEditableTextPara::implGetLineBoundary( const OUString&, css::i18n::Boundary& rBoundary, sal_Int32 nIndex ) |
163 | 0 | { |
164 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
165 | 0 | const sal_Int32 nParaIndex = GetParagraphIndex(); |
166 | |
|
167 | 0 | DBG_ASSERT(nParaIndex >= 0, |
168 | 0 | "AccessibleEditableTextPara::implGetLineBoundary: paragraph index value overflow"); |
169 | |
|
170 | 0 | const sal_Int32 nTextLen = rCacheTF.GetTextLen( nParaIndex ); |
171 | |
|
172 | 0 | CheckPosition(nIndex); |
173 | |
|
174 | 0 | rBoundary.startPos = rBoundary.endPos = -1; |
175 | |
|
176 | 0 | const sal_Int32 nLineCount=rCacheTF.GetLineCount( nParaIndex ); |
177 | |
|
178 | 0 | if( nIndex == nTextLen ) |
179 | 0 | { |
180 | | // #i17014# Special-casing one-behind-the-end character |
181 | 0 | if( nLineCount <= 1 ) |
182 | 0 | rBoundary.startPos = 0; |
183 | 0 | else |
184 | 0 | rBoundary.startPos = nTextLen - rCacheTF.GetLineLen( nParaIndex, |
185 | 0 | nLineCount-1 ); |
186 | |
|
187 | 0 | rBoundary.endPos = nTextLen; |
188 | 0 | } |
189 | 0 | else |
190 | 0 | { |
191 | | // normal line search |
192 | 0 | sal_Int32 nLine; |
193 | 0 | sal_Int32 nCurIndex; |
194 | 0 | for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) |
195 | 0 | { |
196 | 0 | nCurIndex += rCacheTF.GetLineLen( nParaIndex, nLine); |
197 | |
|
198 | 0 | if( nCurIndex > nIndex ) |
199 | 0 | { |
200 | 0 | rBoundary.startPos = nCurIndex - rCacheTF.GetLineLen( nParaIndex, nLine); |
201 | 0 | rBoundary.endPos = nCurIndex; |
202 | 0 | break; |
203 | 0 | } |
204 | 0 | } |
205 | 0 | } |
206 | 0 | } |
207 | | |
208 | | |
209 | | void AccessibleEditableTextPara::SetIndexInParent( sal_Int32 nIndex ) |
210 | 0 | { |
211 | 0 | mnIndexInParent = nIndex; |
212 | 0 | } |
213 | | |
214 | | |
215 | | void AccessibleEditableTextPara::SetParagraphIndex( sal_Int32 nIndex ) |
216 | 0 | { |
217 | 0 | sal_Int32 nOldIndex = mnParagraphIndex; |
218 | |
|
219 | 0 | mnParagraphIndex = nIndex; |
220 | |
|
221 | 0 | auto aChild( maImageBullet.get() ); |
222 | 0 | if( aChild.is() ) |
223 | 0 | aChild->SetParagraphIndex(mnParagraphIndex); |
224 | |
|
225 | 0 | try |
226 | 0 | { |
227 | 0 | if( nOldIndex != nIndex ) |
228 | 0 | { |
229 | 0 | uno::Any aOldDesc; |
230 | 0 | uno::Any aOldName; |
231 | |
|
232 | 0 | try |
233 | 0 | { |
234 | 0 | aOldDesc <<= getAccessibleDescription(); |
235 | 0 | aOldName <<= getAccessibleName(); |
236 | 0 | } |
237 | 0 | catch (const uno::Exception&) // optional behaviour |
238 | 0 | { |
239 | 0 | } |
240 | | // index and therefore description changed |
241 | 0 | FireEvent( AccessibleEventId::DESCRIPTION_CHANGED, uno::Any( getAccessibleDescription() ), aOldDesc ); |
242 | 0 | FireEvent( AccessibleEventId::NAME_CHANGED, uno::Any( getAccessibleName() ), aOldName ); |
243 | 0 | } |
244 | 0 | } |
245 | 0 | catch (const uno::Exception&) // optional behaviour |
246 | 0 | { |
247 | 0 | } |
248 | 0 | } |
249 | | |
250 | | |
251 | | void SAL_CALL AccessibleEditableTextPara::dispose() |
252 | 0 | { |
253 | 0 | rtl::Reference<AccessibleImageBullet> xBullet = maImageBullet.get(); |
254 | 0 | if (xBullet.is()) |
255 | 0 | xBullet->dispose(); |
256 | 0 | maImageBullet.clear(); |
257 | |
|
258 | 0 | mpParent = nullptr; |
259 | 0 | mpEditSource = nullptr; |
260 | |
|
261 | 0 | comphelper::OAccessible::dispose(); |
262 | 0 | } |
263 | | |
264 | | void AccessibleEditableTextPara::SetEditSource( SvxEditSourceAdapter* pEditSource ) |
265 | 0 | { |
266 | 0 | auto aChild( maImageBullet.get() ); |
267 | 0 | if( aChild.is() ) |
268 | 0 | aChild->SetEditSource(pEditSource); |
269 | |
|
270 | 0 | if( !pEditSource ) |
271 | 0 | { |
272 | | // going defunc |
273 | 0 | UnSetState( AccessibleStateType::SHOWING ); |
274 | 0 | UnSetState( AccessibleStateType::VISIBLE ); |
275 | 0 | SetState( AccessibleStateType::INVALID ); |
276 | 0 | SetState( AccessibleStateType::DEFUNC ); |
277 | 0 | } |
278 | 0 | mpEditSource = pEditSource; |
279 | | // #108900# Init last text content |
280 | 0 | try |
281 | 0 | { |
282 | 0 | TextChanged(); |
283 | 0 | } |
284 | 0 | catch (const uno::RuntimeException&) |
285 | 0 | { |
286 | 0 | } |
287 | 0 | } |
288 | | |
289 | | ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nStartEEIndex, sal_Int32 nEndEEIndex ) |
290 | 0 | { |
291 | | // check overflow |
292 | 0 | DBG_ASSERT(nStartEEIndex >= 0 && |
293 | 0 | nEndEEIndex >= 0 && |
294 | 0 | GetParagraphIndex() >= 0, |
295 | 0 | "AccessibleEditableTextPara::MakeSelection: index value overflow"); |
296 | |
|
297 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
298 | 0 | return ESelection(nParaIndex, nStartEEIndex, nParaIndex, nEndEEIndex); |
299 | 0 | } |
300 | | |
301 | | ESelection AccessibleEditableTextPara::MakeSelection( sal_Int32 nEEIndex ) |
302 | 0 | { |
303 | 0 | return MakeSelection( nEEIndex, nEEIndex+1 ); |
304 | 0 | } |
305 | | |
306 | | ESelection AccessibleEditableTextPara::MakeCursor( sal_Int32 nEEIndex ) |
307 | 0 | { |
308 | 0 | return MakeSelection( nEEIndex, nEEIndex ); |
309 | 0 | } |
310 | | |
311 | | void AccessibleEditableTextPara::CheckIndex( sal_Int32 nIndex ) |
312 | 0 | { |
313 | 0 | if( nIndex < 0 || nIndex >= getCharacterCount() ) |
314 | 0 | throw lang::IndexOutOfBoundsException(u"AccessibleEditableTextPara: character index out of bounds"_ustr, |
315 | 0 | getXWeak() ); |
316 | 0 | } |
317 | | |
318 | | void AccessibleEditableTextPara::CheckPosition( sal_Int32 nIndex ) |
319 | 0 | { |
320 | 0 | if( nIndex < 0 || nIndex > getCharacterCount() ) |
321 | 0 | throw lang::IndexOutOfBoundsException(u"AccessibleEditableTextPara: character position out of bounds"_ustr, |
322 | 0 | getXWeak() ); |
323 | 0 | } |
324 | | |
325 | | void AccessibleEditableTextPara::CheckRange( sal_Int32 nStart, sal_Int32 nEnd ) |
326 | 0 | { |
327 | 0 | CheckPosition( nStart ); |
328 | 0 | CheckPosition( nEnd ); |
329 | 0 | } |
330 | | |
331 | | bool AccessibleEditableTextPara::GetSelection(sal_Int32 &nStartPos, sal_Int32 &nEndPos) |
332 | 0 | { |
333 | 0 | ESelection aSelection; |
334 | 0 | sal_Int32 nPara = GetParagraphIndex(); |
335 | 0 | if( !GetEditViewForwarder().GetSelection( aSelection ) ) |
336 | 0 | return false; |
337 | | |
338 | 0 | aSelection.Adjust(); |
339 | |
|
340 | 0 | if (aSelection.start.nPara > nPara || aSelection.end.nPara < nPara) |
341 | 0 | return false; |
342 | | |
343 | 0 | if (nPara == aSelection.start.nPara) |
344 | 0 | nStartPos = aSelection.start.nIndex; |
345 | 0 | else |
346 | 0 | nStartPos = 0; |
347 | |
|
348 | 0 | if (nPara == aSelection.end.nPara) |
349 | 0 | nEndPos = aSelection.end.nIndex; |
350 | 0 | else |
351 | 0 | nEndPos = GetTextLen(); |
352 | |
|
353 | 0 | return true; |
354 | 0 | } |
355 | | |
356 | | OUString AccessibleEditableTextPara::GetTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
357 | 0 | { |
358 | 0 | return GetTextForwarder().GetText( MakeSelection(nStartIndex, nEndIndex) ); |
359 | 0 | } |
360 | | |
361 | | sal_Int32 AccessibleEditableTextPara::GetTextLen() const |
362 | 0 | { |
363 | 0 | return GetTextForwarder().GetTextLen(GetParagraphIndex()); |
364 | 0 | } |
365 | | |
366 | | SvxEditSourceAdapter& AccessibleEditableTextPara::GetEditSource() const |
367 | 0 | { |
368 | 0 | if( !mpEditSource ) |
369 | 0 | throw uno::RuntimeException(u"No edit source, object is defunct"_ustr, |
370 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
371 | 0 | return *mpEditSource; |
372 | 0 | } |
373 | | |
374 | | SvxAccessibleTextAdapter& AccessibleEditableTextPara::GetTextForwarder() const |
375 | 0 | { |
376 | 0 | SvxEditSourceAdapter& rEditSource = GetEditSource(); |
377 | 0 | SvxAccessibleTextAdapter* pTextForwarder = rEditSource.GetTextForwarderAdapter(); |
378 | |
|
379 | 0 | if( !pTextForwarder ) |
380 | 0 | throw uno::RuntimeException(u"Unable to fetch text forwarder, object is defunct"_ustr, |
381 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
382 | | |
383 | 0 | if( !pTextForwarder->IsValid() ) |
384 | 0 | throw uno::RuntimeException(u"Text forwarder is invalid, object is defunct"_ustr, |
385 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
386 | 0 | return *pTextForwarder; |
387 | 0 | } |
388 | | |
389 | | SvxViewForwarder& AccessibleEditableTextPara::GetViewForwarder() const |
390 | 0 | { |
391 | 0 | SvxEditSource& rEditSource = GetEditSource(); |
392 | 0 | SvxViewForwarder* pViewForwarder = rEditSource.GetViewForwarder(); |
393 | |
|
394 | 0 | if( !pViewForwarder ) |
395 | 0 | { |
396 | 0 | throw uno::RuntimeException(u"Unable to fetch view forwarder, object is defunct"_ustr, |
397 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
398 | 0 | } |
399 | | |
400 | 0 | if( !pViewForwarder->IsValid() ) |
401 | 0 | throw uno::RuntimeException(u"View forwarder is invalid, object is defunct"_ustr, |
402 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
403 | 0 | return *pViewForwarder; |
404 | 0 | } |
405 | | |
406 | | SvxAccessibleTextEditViewAdapter& AccessibleEditableTextPara::GetEditViewForwarder( bool bCreate ) const |
407 | 0 | { |
408 | 0 | SvxEditSourceAdapter& rEditSource = GetEditSource(); |
409 | 0 | SvxAccessibleTextEditViewAdapter* pTextEditViewForwarder = rEditSource.GetEditViewForwarderAdapter( bCreate ); |
410 | |
|
411 | 0 | if( !pTextEditViewForwarder ) |
412 | 0 | { |
413 | 0 | if( bCreate ) |
414 | 0 | throw uno::RuntimeException(u"Unable to fetch view forwarder, object is defunct"_ustr, |
415 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
416 | 0 | else |
417 | 0 | throw uno::RuntimeException(u"No view forwarder, object not in edit mode"_ustr, |
418 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
419 | 0 | } |
420 | | |
421 | 0 | if( pTextEditViewForwarder->IsValid() ) |
422 | 0 | return *pTextEditViewForwarder; |
423 | 0 | else |
424 | 0 | { |
425 | 0 | if( bCreate ) |
426 | 0 | throw uno::RuntimeException(u"View forwarder is invalid, object is defunct"_ustr, |
427 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
428 | 0 | else |
429 | 0 | throw uno::RuntimeException(u"View forwarder is invalid, object not in edit mode"_ustr, |
430 | 0 | const_cast< AccessibleEditableTextPara* > (this)->getXWeak() ); |
431 | 0 | } |
432 | 0 | } |
433 | | |
434 | | bool AccessibleEditableTextPara::HaveEditView() const |
435 | 0 | { |
436 | 0 | SvxEditSource& rEditSource = GetEditSource(); |
437 | 0 | SvxEditViewForwarder* pViewForwarder = rEditSource.GetEditViewForwarder(); |
438 | |
|
439 | 0 | if( !pViewForwarder ) |
440 | 0 | return false; |
441 | | |
442 | 0 | if( !pViewForwarder->IsValid() ) |
443 | 0 | return false; |
444 | | |
445 | 0 | return true; |
446 | 0 | } |
447 | | |
448 | | bool AccessibleEditableTextPara::HaveChildren() |
449 | 0 | { |
450 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
451 | 0 | "AccessibleEditableTextPara::HaveChildren: paragraph index value overflow"); |
452 | |
|
453 | 0 | return GetTextForwarder().HaveImageBullet( GetParagraphIndex() ); |
454 | 0 | } |
455 | | |
456 | | sal_Int32 AccessibleEditableTextPara::GetBulletTextLength() const |
457 | 0 | { |
458 | 0 | sal_Int32 nBulletLen = 0; |
459 | 0 | EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex()); |
460 | 0 | if (aBulletInfo.nParagraph != EE_PARA_MAX && aBulletInfo.bVisible) |
461 | 0 | nBulletLen = aBulletInfo.aText.getLength(); |
462 | 0 | return nBulletLen; |
463 | 0 | } |
464 | | |
465 | | tools::Rectangle AccessibleEditableTextPara::LogicToPixel( const tools::Rectangle& rRect, const MapMode& rMapMode, SvxViewForwarder const & rForwarder ) |
466 | 0 | { |
467 | | // convert to screen coordinates |
468 | 0 | return tools::Rectangle( rForwarder.LogicToPixel( rRect.TopLeft(), rMapMode ), |
469 | 0 | rForwarder.LogicToPixel( rRect.BottomRight(), rMapMode ) ); |
470 | 0 | } |
471 | | |
472 | | |
473 | | void AccessibleEditableTextPara::SetEEOffset( const Point& rOffset ) |
474 | 0 | { |
475 | 0 | auto aChild( maImageBullet.get() ); |
476 | 0 | if( aChild.is() ) |
477 | 0 | aChild->SetEEOffset(rOffset); |
478 | |
|
479 | 0 | maEEOffset = rOffset; |
480 | 0 | } |
481 | | |
482 | | void AccessibleEditableTextPara::FireEvent(const sal_Int16 nEventId, const uno::Any& rNewValue, const uno::Any& rOldValue) |
483 | 0 | { |
484 | 0 | NotifyAccessibleEvent(nEventId, rOldValue, rNewValue); |
485 | 0 | } |
486 | | |
487 | | void AccessibleEditableTextPara::SetState( const sal_Int64 nStateId ) |
488 | 0 | { |
489 | 0 | if( !(mnStateSet & nStateId) ) |
490 | 0 | { |
491 | 0 | mnStateSet |= nStateId; |
492 | 0 | FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any( nStateId ) ); |
493 | 0 | } |
494 | 0 | } |
495 | | |
496 | | void AccessibleEditableTextPara::UnSetState( const sal_Int64 nStateId ) |
497 | 0 | { |
498 | 0 | if( mnStateSet & nStateId ) |
499 | 0 | { |
500 | 0 | mnStateSet &= ~nStateId; |
501 | 0 | FireEvent( AccessibleEventId::STATE_CHANGED, uno::Any(), uno::Any( nStateId ) ); |
502 | 0 | } |
503 | 0 | } |
504 | | |
505 | | void AccessibleEditableTextPara::TextChanged() |
506 | 0 | { |
507 | 0 | OUString aCurrentString( implGetText() ); |
508 | 0 | uno::Any aDeleted; |
509 | 0 | uno::Any aInserted; |
510 | 0 | if( OCommonAccessibleText::implInitTextChangedEvent( maLastTextString, aCurrentString, |
511 | 0 | aDeleted, aInserted) ) |
512 | 0 | { |
513 | 0 | FireEvent( AccessibleEventId::TEXT_CHANGED, aInserted, aDeleted ); |
514 | 0 | maLastTextString = aCurrentString; |
515 | 0 | } |
516 | 0 | } |
517 | | |
518 | | bool AccessibleEditableTextPara::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nIndex ) |
519 | 0 | { |
520 | 0 | DBG_ASSERT(nIndex >= 0, |
521 | 0 | "AccessibleEditableTextPara::GetAttributeRun: index value overflow"); |
522 | |
|
523 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
524 | 0 | "AccessibleEditableTextPara::getLocale: paragraph index value overflow"); |
525 | |
|
526 | 0 | return GetTextForwarder().GetAttributeRun( nStartIndex, |
527 | 0 | nEndIndex, |
528 | 0 | GetParagraphIndex(), |
529 | 0 | nIndex ); |
530 | 0 | } |
531 | | |
532 | | // XAccessibleContext |
533 | | sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleChildCount() |
534 | 0 | { |
535 | 0 | SolarMutexGuard aGuard; |
536 | |
|
537 | 0 | return HaveChildren() ? 1 : 0; |
538 | 0 | } |
539 | | |
540 | | uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleChild( sal_Int64 i ) |
541 | 0 | { |
542 | 0 | SolarMutexGuard aGuard; |
543 | |
|
544 | 0 | if( !HaveChildren() ) |
545 | 0 | throw lang::IndexOutOfBoundsException(u"No children available"_ustr, |
546 | 0 | getXWeak() ); |
547 | | |
548 | 0 | if( i != 0 ) |
549 | 0 | throw lang::IndexOutOfBoundsException(u"Invalid child index"_ustr, |
550 | 0 | getXWeak() ); |
551 | | |
552 | 0 | auto aChild( maImageBullet.get() ); |
553 | |
|
554 | 0 | if( !aChild.is() ) |
555 | 0 | { |
556 | | // there is no hard reference available, create object then |
557 | 0 | aChild = new AccessibleImageBullet(this, i); |
558 | |
|
559 | 0 | aChild->SetEditSource( &GetEditSource() ); |
560 | 0 | aChild->SetParagraphIndex( GetParagraphIndex() ); |
561 | |
|
562 | 0 | maImageBullet = aChild.get(); |
563 | 0 | } |
564 | |
|
565 | 0 | return aChild; |
566 | 0 | } |
567 | | |
568 | | uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleParent() |
569 | 0 | { |
570 | 0 | SAL_WARN_IF(!mpParent.is(), "editeng", "AccessibleEditableTextPara::getAccessibleParent: no frontend set, did somebody forgot to call AccessibleTextHelper::SetEventSource()?"); |
571 | | |
572 | 0 | return mpParent; |
573 | 0 | } |
574 | | |
575 | | sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleIndexInParent() |
576 | 0 | { |
577 | 0 | return mnIndexInParent; |
578 | 0 | } |
579 | | |
580 | | sal_Int16 SAL_CALL AccessibleEditableTextPara::getAccessibleRole() |
581 | 0 | { |
582 | 0 | return AccessibleRole::PARAGRAPH; |
583 | 0 | } |
584 | | |
585 | | OUString SAL_CALL AccessibleEditableTextPara::getAccessibleDescription() |
586 | 0 | { |
587 | 0 | return OUString(); |
588 | 0 | } |
589 | | |
590 | | OUString SAL_CALL AccessibleEditableTextPara::getAccessibleName() |
591 | 0 | { |
592 | | //See tdf#101003 before implementing a body |
593 | 0 | return OUString(); |
594 | 0 | } |
595 | | |
596 | | uno::Reference< XAccessibleRelationSet > SAL_CALL AccessibleEditableTextPara::getAccessibleRelationSet() |
597 | 0 | { |
598 | | // #i27138# - provide relations CONTENT_FLOWS_FROM |
599 | | // and CONTENT_FLOWS_TO |
600 | 0 | if ( mpParaManager ) |
601 | 0 | { |
602 | 0 | rtl::Reference<utl::AccessibleRelationSetHelper> pAccRelSetHelper = |
603 | 0 | new utl::AccessibleRelationSetHelper(); |
604 | 0 | sal_Int32 nMyParaIndex( GetParagraphIndex() ); |
605 | | // relation CONTENT_FLOWS_FROM |
606 | 0 | if ( nMyParaIndex > 0 && |
607 | 0 | mpParaManager->IsReferencable( nMyParaIndex - 1 ) ) |
608 | 0 | { |
609 | 0 | uno::Sequence<uno::Reference<XAccessible>> aSequence |
610 | 0 | { mpParaManager->GetChild( nMyParaIndex - 1 ).first.get() }; |
611 | 0 | AccessibleRelation aAccRel(AccessibleRelationType_CONTENT_FLOWS_FROM, |
612 | 0 | aSequence ); |
613 | 0 | pAccRelSetHelper->AddRelation( aAccRel ); |
614 | 0 | } |
615 | | |
616 | | // relation CONTENT_FLOWS_TO |
617 | 0 | if ( (nMyParaIndex + 1) < mpParaManager->GetNum() && |
618 | 0 | mpParaManager->IsReferencable( nMyParaIndex + 1 ) ) |
619 | 0 | { |
620 | 0 | uno::Sequence<uno::Reference<XAccessible>> aSequence |
621 | 0 | { mpParaManager->GetChild( nMyParaIndex + 1 ).first.get() }; |
622 | 0 | AccessibleRelation aAccRel(AccessibleRelationType_CONTENT_FLOWS_TO, |
623 | 0 | aSequence ); |
624 | 0 | pAccRelSetHelper->AddRelation( aAccRel ); |
625 | 0 | } |
626 | |
|
627 | 0 | return pAccRelSetHelper; |
628 | 0 | } |
629 | 0 | else |
630 | 0 | { |
631 | | // no relations, therefore empty |
632 | 0 | return uno::Reference< XAccessibleRelationSet >(); |
633 | 0 | } |
634 | 0 | } |
635 | | |
636 | | static uno::Sequence< OUString > const & getAttributeNames() |
637 | 0 | { |
638 | 0 | static const uno::Sequence<OUString> aNames{ |
639 | 0 | u"CharColor"_ustr, |
640 | 0 | u"CharContoured"_ustr, |
641 | 0 | u"CharEmphasis"_ustr, |
642 | 0 | u"CharEscapement"_ustr, |
643 | 0 | u"CharFontName"_ustr, |
644 | 0 | u"CharHeight"_ustr, |
645 | 0 | u"CharPosture"_ustr, |
646 | 0 | u"CharShadowed"_ustr, |
647 | 0 | u"CharStrikeout"_ustr, |
648 | 0 | u"CharCaseMap"_ustr, |
649 | 0 | u"CharUnderline"_ustr, |
650 | 0 | u"CharUnderlineColor"_ustr, |
651 | 0 | u"CharWeight"_ustr, |
652 | 0 | u"NumberingLevel"_ustr, |
653 | 0 | u"NumberingRules"_ustr, |
654 | 0 | u"ParaAdjust"_ustr, |
655 | 0 | u"ParaBottomMargin"_ustr, |
656 | 0 | u"ParaFirstLineIndent"_ustr, |
657 | 0 | u"ParaLeftMargin"_ustr, |
658 | 0 | u"ParaLineSpacing"_ustr, |
659 | 0 | u"ParaRightMargin"_ustr, |
660 | 0 | u"ParaTabStops"_ustr}; |
661 | |
|
662 | 0 | return aNames; |
663 | 0 | } |
664 | | |
665 | | namespace { |
666 | | |
667 | | struct IndexCompare |
668 | | { |
669 | | const uno::Sequence<beans::PropertyValue>& m_rValues; |
670 | | explicit IndexCompare(const uno::Sequence<beans::PropertyValue>& rValues) |
671 | 0 | : m_rValues(rValues) |
672 | 0 | { |
673 | 0 | } |
674 | | bool operator() ( sal_Int32 a, sal_Int32 b ) const |
675 | 0 | { |
676 | 0 | return m_rValues[a].Name < m_rValues[b].Name; |
677 | 0 | } |
678 | | }; |
679 | | |
680 | | } |
681 | | } |
682 | | |
683 | | namespace |
684 | | { |
685 | | OUString GetFieldTypeNameFromField(EFieldInfo const &ree) |
686 | 0 | { |
687 | 0 | OUString strFldType; |
688 | 0 | sal_Int32 nFieldType = -1; |
689 | 0 | if (ree.pFieldItem) |
690 | 0 | { |
691 | | // So we get a field, check its type now. |
692 | 0 | nFieldType = ree.pFieldItem->GetField()->GetClassId() ; |
693 | 0 | } |
694 | 0 | switch (nFieldType) |
695 | 0 | { |
696 | 0 | case text::textfield::Type::DATE: |
697 | 0 | { |
698 | 0 | const SvxDateField* pDateField = static_cast< const SvxDateField* >(ree.pFieldItem->GetField()); |
699 | 0 | if (pDateField) |
700 | 0 | { |
701 | 0 | if (pDateField->GetType() == SvxDateType::Fix) |
702 | 0 | strFldType = "date (fixed)"; |
703 | 0 | else if (pDateField->GetType() == SvxDateType::Var) |
704 | 0 | strFldType = "date (variable)"; |
705 | 0 | } |
706 | 0 | break; |
707 | 0 | } |
708 | 0 | case text::textfield::Type::PAGE: |
709 | 0 | strFldType = "page-number"; |
710 | 0 | break; |
711 | | //support the sheet name & pages fields |
712 | 0 | case text::textfield::Type::PAGES: |
713 | 0 | strFldType = "page-count"; |
714 | 0 | break; |
715 | 0 | case text::textfield::Type::TABLE: |
716 | 0 | strFldType = "sheet-name"; |
717 | 0 | break; |
718 | | //End |
719 | 0 | case text::textfield::Type::TIME: |
720 | 0 | strFldType = "time"; |
721 | 0 | break; |
722 | 0 | case text::textfield::Type::EXTENDED_TIME: |
723 | 0 | { |
724 | 0 | const SvxExtTimeField* pTimeField = static_cast< const SvxExtTimeField* >(ree.pFieldItem->GetField()); |
725 | 0 | if (pTimeField) |
726 | 0 | { |
727 | 0 | if (pTimeField->GetType() == SvxTimeType::Fix) |
728 | 0 | strFldType = "time (fixed)"; |
729 | 0 | else if (pTimeField->GetType() == SvxTimeType::Var) |
730 | 0 | strFldType = "time (variable)"; |
731 | 0 | } |
732 | 0 | break; |
733 | 0 | } |
734 | 0 | case text::textfield::Type::AUTHOR: |
735 | 0 | strFldType = "author"; |
736 | 0 | break; |
737 | 0 | case text::textfield::Type::EXTENDED_FILE: |
738 | 0 | case text::textfield::Type::DOCINFO_TITLE: |
739 | 0 | strFldType = "file name"; |
740 | 0 | break; |
741 | 0 | case text::textfield::Type::DOCINFO_CUSTOM: |
742 | 0 | strFldType = "custom document property"; |
743 | 0 | break; |
744 | 0 | default: |
745 | 0 | break; |
746 | 0 | } |
747 | 0 | return strFldType; |
748 | 0 | } |
749 | | } |
750 | | |
751 | | namespace accessibility |
752 | | { |
753 | | OUString AccessibleEditableTextPara::GetFieldTypeNameAtIndex(sal_Int32 nIndex) |
754 | 0 | { |
755 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); |
756 | | //For field object info |
757 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
758 | 0 | sal_Int32 nAllFieldLen = 0; |
759 | 0 | std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex); |
760 | 0 | for (const EFieldInfo& ree : aFieldInfos) |
761 | 0 | { |
762 | 0 | sal_Int32 reeBegin = ree.aPosition.nIndex + nAllFieldLen; |
763 | 0 | sal_Int32 reeEnd = reeBegin + ree.aCurrentText.getLength(); |
764 | 0 | nAllFieldLen += (ree.aCurrentText.getLength() - 1); |
765 | 0 | if (nIndex < reeBegin) |
766 | 0 | break; |
767 | 0 | if (nIndex < reeEnd) |
768 | 0 | return GetFieldTypeNameFromField(ree); |
769 | 0 | } |
770 | 0 | return OUString(); |
771 | 0 | } |
772 | | |
773 | | sal_Int64 SAL_CALL AccessibleEditableTextPara::getAccessibleStateSet() |
774 | 0 | { |
775 | 0 | SolarMutexGuard aGuard; |
776 | | |
777 | | // Create a copy of the state set and return it. |
778 | |
|
779 | 0 | sal_Int64 nParentStates = 0; |
780 | 0 | if (getAccessibleParent().is()) |
781 | 0 | { |
782 | 0 | uno::Reference<XAccessibleContext> xParentContext = getAccessibleParent()->getAccessibleContext(); |
783 | 0 | nParentStates = xParentContext->getAccessibleStateSet(); |
784 | 0 | } |
785 | 0 | if (nParentStates & AccessibleStateType::EDITABLE) |
786 | 0 | { |
787 | 0 | mnStateSet |= AccessibleStateType::EDITABLE; |
788 | 0 | } |
789 | 0 | return mnStateSet; |
790 | 0 | } |
791 | | |
792 | | lang::Locale SAL_CALL AccessibleEditableTextPara::getLocale() |
793 | 0 | { |
794 | 0 | SolarMutexGuard aGuard; |
795 | |
|
796 | 0 | return implGetLocale(); |
797 | 0 | } |
798 | | |
799 | | // XAccessibleComponent |
800 | | |
801 | | uno::Reference< XAccessible > SAL_CALL AccessibleEditableTextPara::getAccessibleAtPoint( const awt::Point& _aPoint ) |
802 | 0 | { |
803 | 0 | SolarMutexGuard aGuard; |
804 | |
|
805 | 0 | if( HaveChildren() ) |
806 | 0 | { |
807 | | // #103862# No longer need to make given position relative |
808 | 0 | Point aPoint( _aPoint.X, _aPoint.Y ); |
809 | | |
810 | | // respect EditEngine offset to surrounding shape/cell |
811 | 0 | aPoint -= GetEEOffset(); |
812 | | |
813 | | // convert to EditEngine coordinate system |
814 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
815 | 0 | Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); |
816 | |
|
817 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex()); |
818 | |
|
819 | 0 | if( aBulletInfo.nParagraph != EE_PARA_MAX && |
820 | 0 | aBulletInfo.bVisible && |
821 | 0 | aBulletInfo.nType == SVX_NUM_BITMAP ) |
822 | 0 | { |
823 | 0 | tools::Rectangle aRect = aBulletInfo.aBounds; |
824 | |
|
825 | 0 | if( aRect.Contains( aLogPoint ) ) |
826 | 0 | return getAccessibleChild(0); |
827 | 0 | } |
828 | 0 | } |
829 | | |
830 | | // no children at all, or none at given position |
831 | 0 | return uno::Reference< XAccessible >(); |
832 | 0 | } |
833 | | |
834 | | awt::Rectangle AccessibleEditableTextPara::implGetBounds() |
835 | 0 | { |
836 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
837 | 0 | "AccessibleEditableTextPara::implGetBounds: index value overflow"); |
838 | |
|
839 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
840 | 0 | tools::Rectangle aRect = rCacheTF.GetParaBounds( GetParagraphIndex() ); |
841 | | |
842 | | // convert to screen coordinates |
843 | 0 | tools::Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, |
844 | 0 | rCacheTF.GetMapMode(), |
845 | 0 | GetViewForwarder() ); |
846 | | |
847 | | // offset from shape/cell |
848 | 0 | Point aOffset = GetEEOffset(); |
849 | |
|
850 | 0 | return awt::Rectangle( aScreenRect.Left() + aOffset.X(), |
851 | 0 | aScreenRect.Top() + aOffset.Y(), |
852 | 0 | aScreenRect.GetSize().Width(), |
853 | 0 | aScreenRect.GetSize().Height() ); |
854 | 0 | } |
855 | | |
856 | | void SAL_CALL AccessibleEditableTextPara::grabFocus( ) |
857 | 0 | { |
858 | | // set cursor to this paragraph |
859 | 0 | setSelection(0,0); |
860 | 0 | } |
861 | | |
862 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getForeground( ) |
863 | 0 | { |
864 | | // #104444# Added to XAccessibleComponent interface |
865 | 0 | svtools::ColorConfig aColorConfig; |
866 | 0 | Color nColor = aColorConfig.GetColorValue( svtools::FONTCOLOR ).nColor; |
867 | 0 | return static_cast<sal_Int32>(nColor); |
868 | 0 | } |
869 | | |
870 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getBackground( ) |
871 | 0 | { |
872 | | // #104444# Added to XAccessibleComponent interface |
873 | 0 | Color aColor( Application::GetSettings().GetStyleSettings().GetWindowColor() ); |
874 | | |
875 | | // the background is transparent |
876 | 0 | aColor.SetAlpha(0); |
877 | |
|
878 | 0 | return static_cast<sal_Int32>( aColor ); |
879 | 0 | } |
880 | | |
881 | | // XAccessibleText |
882 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getCaretPosition() |
883 | 0 | { |
884 | 0 | SolarMutexGuard aGuard; |
885 | |
|
886 | 0 | if( !HaveEditView() ) |
887 | 0 | return -1; |
888 | | |
889 | 0 | ESelection aSelection; |
890 | 0 | if( GetEditViewForwarder().GetSelection( aSelection ) && |
891 | 0 | GetParagraphIndex() == aSelection.end.nPara ) |
892 | 0 | { |
893 | | // caret is always nEndPara,nEndPos |
894 | 0 | EBulletInfo aBulletInfo = GetTextForwarder().GetBulletInfo(GetParagraphIndex()); |
895 | 0 | if( aBulletInfo.nParagraph != EE_PARA_MAX && |
896 | 0 | aBulletInfo.bVisible && |
897 | 0 | aBulletInfo.nType != SVX_NUM_BITMAP ) |
898 | 0 | { |
899 | 0 | sal_Int32 nBulletLen = aBulletInfo.aText.getLength(); |
900 | 0 | if( aSelection.end.nIndex - nBulletLen >= 0 ) |
901 | 0 | return aSelection.end.nIndex - nBulletLen; |
902 | 0 | } |
903 | 0 | return aSelection.end.nIndex; |
904 | 0 | } |
905 | | |
906 | | // not within this paragraph |
907 | 0 | return -1; |
908 | 0 | } |
909 | | |
910 | | sal_Bool SAL_CALL AccessibleEditableTextPara::setCaretPosition( sal_Int32 nIndex ) |
911 | 0 | { |
912 | 0 | return setSelection(nIndex, nIndex); |
913 | 0 | } |
914 | | |
915 | | sal_Unicode SAL_CALL AccessibleEditableTextPara::getCharacter( sal_Int32 nIndex ) |
916 | 0 | { |
917 | 0 | SolarMutexGuard aGuard; |
918 | |
|
919 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
920 | 0 | "AccessibleEditableTextPara::getCharacter: index value overflow"); |
921 | |
|
922 | 0 | return OCommonAccessibleText::implGetCharacter( implGetText(), nIndex ); |
923 | 0 | } |
924 | | |
925 | | uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& rRequestedAttributes ) |
926 | 0 | { |
927 | 0 | SolarMutexGuard aGuard; |
928 | | |
929 | | //Skip the bullet range to ignore the bullet text |
930 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
931 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex()); |
932 | 0 | if (aBulletInfo.bVisible) |
933 | 0 | nIndex += aBulletInfo.aText.getLength(); |
934 | 0 | CheckIndex(nIndex); // may throw IndexOutOfBoundsException |
935 | |
|
936 | 0 | bool bSupplementalMode = false; |
937 | 0 | uno::Sequence< OUString > aPropertyNames = rRequestedAttributes; |
938 | 0 | if (!aPropertyNames.hasElements()) |
939 | 0 | { |
940 | 0 | bSupplementalMode = true; |
941 | 0 | aPropertyNames = getAttributeNames(); |
942 | 0 | } |
943 | | |
944 | | // get default attributes... |
945 | 0 | ::comphelper::SequenceAsHashMap aPropHashMap( getDefaultAttributes( aPropertyNames ) ); |
946 | | |
947 | | // ... and override them with the direct attributes from the specific position |
948 | 0 | const uno::Sequence< beans::PropertyValue > aRunAttribs( getRunAttributes( nIndex, aPropertyNames ) ); |
949 | 0 | for (auto const& rRunAttrib : aRunAttribs) |
950 | 0 | { |
951 | 0 | aPropHashMap[ rRunAttrib.Name ] = rRunAttrib.Value; //!! should not only be the value !! |
952 | 0 | } |
953 | | |
954 | | // get resulting sequence |
955 | 0 | uno::Sequence< beans::PropertyValue > aRes; |
956 | 0 | aPropHashMap >> aRes; |
957 | | |
958 | | // since SequenceAsHashMap ignores property handles and property state |
959 | | // we have to restore the property state here (property handles are |
960 | | // of no use to the accessibility API). |
961 | 0 | for (beans::PropertyValue & rRes : asNonConstRange(aRes)) |
962 | 0 | { |
963 | 0 | bool bIsDirectVal = false; |
964 | 0 | for (auto const& rRunAttrib : aRunAttribs) |
965 | 0 | { |
966 | 0 | bIsDirectVal = rRes.Name == rRunAttrib.Name; |
967 | 0 | if (bIsDirectVal) |
968 | 0 | break; |
969 | 0 | } |
970 | 0 | rRes.Handle = -1; |
971 | 0 | rRes.State = bIsDirectVal ? PropertyState_DIRECT_VALUE : PropertyState_DEFAULT_VALUE; |
972 | 0 | } |
973 | 0 | if( bSupplementalMode ) |
974 | 0 | { |
975 | 0 | _correctValues( aRes ); |
976 | | // NumberingPrefix |
977 | 0 | sal_Int32 nRes = aRes.getLength(); |
978 | 0 | aRes.realloc( nRes + 1 ); |
979 | 0 | beans::PropertyValue &rRes = aRes.getArray()[nRes]; |
980 | 0 | rRes.Name = "NumberingPrefix"; |
981 | 0 | OUString numStr; |
982 | 0 | if (aBulletInfo.nType != SVX_NUM_CHAR_SPECIAL && aBulletInfo.nType != SVX_NUM_BITMAP) |
983 | 0 | numStr = aBulletInfo.aText; |
984 | 0 | rRes.Value <<= numStr; |
985 | 0 | rRes.Handle = -1; |
986 | 0 | rRes.State = PropertyState_DIRECT_VALUE; |
987 | | //For field object. |
988 | 0 | OUString strFieldType = GetFieldTypeNameAtIndex(nIndex); |
989 | 0 | if (!strFieldType.isEmpty()) |
990 | 0 | { |
991 | 0 | nRes = aRes.getLength(); |
992 | 0 | aRes.realloc( nRes + 1 ); |
993 | 0 | beans::PropertyValue &rResField = aRes.getArray()[nRes]; |
994 | 0 | rResField.Name = "FieldType"; |
995 | 0 | rResField.Value <<= strFieldType.toAsciiLowerCase(); |
996 | 0 | rResField.Handle = -1; |
997 | 0 | rResField.State = PropertyState_DIRECT_VALUE; |
998 | 0 | } |
999 | | //sort property values |
1000 | | // build sorted index array |
1001 | 0 | sal_Int32 nLength = aRes.getLength(); |
1002 | 0 | std::vector<sal_Int32> indices(nLength); |
1003 | 0 | std::iota(indices.begin(), indices.end(), 0); |
1004 | 0 | std::sort(indices.begin(), indices.end(), IndexCompare(aRes)); |
1005 | | // create sorted sequences according to index array |
1006 | 0 | uno::Sequence<beans::PropertyValue> aNewValues( nLength ); |
1007 | 0 | std::transform(indices.begin(), indices.end(), aNewValues.getArray(), |
1008 | 0 | [&aRes](sal_Int32 index) -> const beans::PropertyValue& { return aRes[index]; }); |
1009 | |
|
1010 | 0 | return aNewValues; |
1011 | 0 | } |
1012 | 0 | return aRes; |
1013 | 0 | } |
1014 | | |
1015 | | awt::Rectangle SAL_CALL AccessibleEditableTextPara::getCharacterBounds( sal_Int32 nIndex ) |
1016 | 0 | { |
1017 | 0 | SolarMutexGuard aGuard; |
1018 | |
|
1019 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1020 | 0 | "AccessibleEditableTextPara::getCharacterBounds: index value overflow"); |
1021 | | |
1022 | | // #108900# Have position semantics now for nIndex, as |
1023 | | // one-past-the-end values are legal, too. |
1024 | 0 | CheckPosition( nIndex ); |
1025 | |
|
1026 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1027 | 0 | tools::Rectangle aRect = rCacheTF.GetCharBounds(GetParagraphIndex(), nIndex); |
1028 | | |
1029 | | // convert to screen |
1030 | 0 | tools::Rectangle aScreenRect = AccessibleEditableTextPara::LogicToPixel( aRect, |
1031 | 0 | rCacheTF.GetMapMode(), |
1032 | 0 | GetViewForwarder() ); |
1033 | | // #109864# offset from parent (paragraph), but in screen |
1034 | | // coordinates. This makes sure the internal text offset in |
1035 | | // the outline view forwarder gets cancelled out here |
1036 | 0 | awt::Rectangle aParaRect( getBounds() ); |
1037 | 0 | aScreenRect.Move( -aParaRect.X, -aParaRect.Y ); |
1038 | | |
1039 | | // offset from shape/cell |
1040 | 0 | Point aOffset = GetEEOffset(); |
1041 | |
|
1042 | 0 | return awt::Rectangle( aScreenRect.Left() + aOffset.X(), |
1043 | 0 | aScreenRect.Top() + aOffset.Y(), |
1044 | 0 | aScreenRect.GetSize().Width(), |
1045 | 0 | aScreenRect.GetSize().Height() ); |
1046 | 0 | } |
1047 | | |
1048 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getCharacterCount() |
1049 | 0 | { |
1050 | 0 | SolarMutexGuard aGuard; |
1051 | |
|
1052 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1053 | 0 | "AccessibleEditableTextPara::getCharacterCount: index value overflow"); |
1054 | |
|
1055 | 0 | return implGetText().getLength(); |
1056 | 0 | } |
1057 | | |
1058 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getIndexAtPoint( const awt::Point& rPoint ) |
1059 | 0 | { |
1060 | 0 | SolarMutexGuard aGuard; |
1061 | |
|
1062 | 0 | sal_Int32 nPara; |
1063 | 0 | sal_Int32 nIndex; |
1064 | | |
1065 | | // offset from surrounding cell/shape |
1066 | 0 | Point aOffset( GetEEOffset() ); |
1067 | 0 | Point aPoint( rPoint.X - aOffset.X(), rPoint.Y - aOffset.Y() ); |
1068 | | |
1069 | | // convert to logical coordinates |
1070 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1071 | 0 | Point aLogPoint( GetViewForwarder().PixelToLogic( aPoint, rCacheTF.GetMapMode() ) ); |
1072 | | |
1073 | | // re-offset to parent (paragraph) |
1074 | 0 | tools::Rectangle aParaRect = rCacheTF.GetParaBounds( GetParagraphIndex() ); |
1075 | 0 | aLogPoint.Move( aParaRect.Left(), aParaRect.Top() ); |
1076 | |
|
1077 | 0 | if( rCacheTF.GetIndexAtPoint( aLogPoint, nPara, nIndex ) && |
1078 | 0 | GetParagraphIndex() == nPara ) |
1079 | 0 | { |
1080 | | // #102259# Double-check if we're _really_ on the given character |
1081 | 0 | try |
1082 | 0 | { |
1083 | 0 | awt::Rectangle aRect1( getCharacterBounds(nIndex) ); |
1084 | 0 | tools::Rectangle aRect2( aRect1.X, aRect1.Y, |
1085 | 0 | aRect1.Width + aRect1.X, aRect1.Height + aRect1.Y ); |
1086 | 0 | if( aRect2.Contains( Point( rPoint.X, rPoint.Y ) ) ) |
1087 | 0 | return nIndex; |
1088 | 0 | else |
1089 | 0 | return -1; |
1090 | 0 | } |
1091 | 0 | catch (const lang::IndexOutOfBoundsException&) |
1092 | 0 | { |
1093 | | // #103927# Don't throw for invalid nIndex values |
1094 | 0 | return -1; |
1095 | 0 | } |
1096 | 0 | } |
1097 | 0 | else |
1098 | 0 | { |
1099 | | // not within our paragraph |
1100 | 0 | return -1; |
1101 | 0 | } |
1102 | 0 | } |
1103 | | |
1104 | | OUString SAL_CALL AccessibleEditableTextPara::getSelectedText() |
1105 | 0 | { |
1106 | 0 | SolarMutexGuard aGuard; |
1107 | |
|
1108 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1109 | 0 | "AccessibleEditableTextPara::getSelectedText: index value overflow"); |
1110 | |
|
1111 | 0 | if( !HaveEditView() ) |
1112 | 0 | return OUString(); |
1113 | | |
1114 | 0 | return OCommonAccessibleText::getSelectedText(); |
1115 | 0 | } |
1116 | | |
1117 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionStart() |
1118 | 0 | { |
1119 | 0 | SolarMutexGuard aGuard; |
1120 | |
|
1121 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1122 | 0 | "AccessibleEditableTextPara::getSelectionStart: index value overflow"); |
1123 | |
|
1124 | 0 | if( !HaveEditView() ) |
1125 | 0 | return -1; |
1126 | | |
1127 | 0 | return OCommonAccessibleText::getSelectionStart(); |
1128 | 0 | } |
1129 | | |
1130 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getSelectionEnd() |
1131 | 0 | { |
1132 | 0 | SolarMutexGuard aGuard; |
1133 | |
|
1134 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1135 | 0 | "AccessibleEditableTextPara::getSelectionEnd: index value overflow"); |
1136 | |
|
1137 | 0 | if( !HaveEditView() ) |
1138 | 0 | return -1; |
1139 | | |
1140 | 0 | return OCommonAccessibleText::getSelectionEnd(); |
1141 | 0 | } |
1142 | | |
1143 | | sal_Bool SAL_CALL AccessibleEditableTextPara::setSelection( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
1144 | 0 | { |
1145 | 0 | SolarMutexGuard aGuard; |
1146 | |
|
1147 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1148 | 0 | "AccessibleEditableTextPara::setSelection: paragraph index value overflow"); |
1149 | |
|
1150 | 0 | CheckRange(nStartIndex, nEndIndex); |
1151 | |
|
1152 | 0 | try |
1153 | 0 | { |
1154 | 0 | SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true ); |
1155 | 0 | return rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); |
1156 | 0 | } |
1157 | 0 | catch (const uno::RuntimeException&) |
1158 | 0 | { |
1159 | 0 | return false; |
1160 | 0 | } |
1161 | 0 | } |
1162 | | |
1163 | | OUString SAL_CALL AccessibleEditableTextPara::getText() |
1164 | 0 | { |
1165 | 0 | SolarMutexGuard aGuard; |
1166 | |
|
1167 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1168 | 0 | "AccessibleEditableTextPara::getText: paragraph index value overflow"); |
1169 | |
|
1170 | 0 | return implGetText(); |
1171 | 0 | } |
1172 | | |
1173 | | OUString SAL_CALL AccessibleEditableTextPara::getTextRange( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
1174 | 0 | { |
1175 | 0 | SolarMutexGuard aGuard; |
1176 | |
|
1177 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1178 | 0 | "AccessibleEditableTextPara::getTextRange: paragraph index value overflow"); |
1179 | |
|
1180 | 0 | return OCommonAccessibleText::implGetTextRange(implGetText(), nStartIndex, nEndIndex); |
1181 | 0 | } |
1182 | | |
1183 | | void AccessibleEditableTextPara::_correctValues( uno::Sequence< PropertyValue >& rValues) |
1184 | 0 | { |
1185 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1186 | 0 | sal_Int32 nRes = rValues.getLength(); |
1187 | 0 | beans::PropertyValue *pRes = rValues.getArray(); |
1188 | 0 | for (sal_Int32 i = 0; i < nRes; ++i) |
1189 | 0 | { |
1190 | 0 | beans::PropertyValue &rRes = pRes[i]; |
1191 | | // Char color |
1192 | 0 | if (rRes.Name == "CharColor") |
1193 | 0 | { |
1194 | 0 | uno::Any &anyChar = rRes.Value; |
1195 | 0 | Color crChar; |
1196 | 0 | anyChar >>= crChar; |
1197 | 0 | if (COL_AUTO == crChar ) |
1198 | 0 | { |
1199 | 0 | if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE |
1200 | 0 | || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL) |
1201 | 0 | { |
1202 | 0 | anyChar <<= COL_BLACK; |
1203 | 0 | } |
1204 | 0 | else |
1205 | 0 | { |
1206 | 0 | Color cr(ColorTransparency, mpParent->getBackground()); |
1207 | 0 | crChar = cr.IsDark() ? COL_WHITE : COL_BLACK; |
1208 | 0 | anyChar <<= crChar; |
1209 | 0 | } |
1210 | 0 | } |
1211 | 0 | continue; |
1212 | 0 | } |
1213 | | // Underline |
1214 | 0 | if (rRes.Name == "CharUnderline") |
1215 | 0 | { |
1216 | 0 | continue; |
1217 | 0 | } |
1218 | | // Underline color && Mis-spell |
1219 | 0 | if (rRes.Name == "CharUnderlineColor") |
1220 | 0 | { |
1221 | 0 | uno::Any &anyCharUnderLine = rRes.Value; |
1222 | 0 | Color crCharUnderLine; |
1223 | 0 | anyCharUnderLine >>= crCharUnderLine; |
1224 | 0 | if (COL_AUTO == crCharUnderLine ) |
1225 | 0 | { |
1226 | 0 | if (mpParent->getAccessibleRole() == AccessibleRole::SHAPE |
1227 | 0 | || mpParent->getAccessibleRole() == AccessibleRole::TABLE_CELL) |
1228 | 0 | { |
1229 | 0 | anyCharUnderLine <<= COL_BLACK; |
1230 | 0 | } |
1231 | 0 | else |
1232 | 0 | { |
1233 | 0 | Color cr(ColorTransparency, mpParent->getBackground()); |
1234 | 0 | crCharUnderLine = cr.IsDark() ? COL_WHITE : COL_BLACK; |
1235 | 0 | anyCharUnderLine <<= crCharUnderLine; |
1236 | 0 | } |
1237 | 0 | } |
1238 | 0 | continue; |
1239 | 0 | } |
1240 | | // NumberingLevel |
1241 | 0 | if (rRes.Name == "NumberingLevel") |
1242 | 0 | { |
1243 | 0 | if(rCacheTF.GetParaAttribs(GetParagraphIndex()).Get(EE_PARA_NUMBULLET).GetNumRule().GetLevelCount()==0) |
1244 | 0 | { |
1245 | 0 | rRes.Value <<= sal_Int16(-1); |
1246 | 0 | rRes.Handle = -1; |
1247 | 0 | rRes.State = PropertyState_DIRECT_VALUE; |
1248 | 0 | } |
1249 | 0 | else |
1250 | 0 | { |
1251 | | // SvxAccessibleTextPropertySet aPropSet( &GetEditSource(), |
1252 | | // ImplGetSvxCharAndParaPropertiesMap() ); |
1253 | | // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap |
1254 | 0 | rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() ) ); |
1255 | |
|
1256 | 0 | xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) ); |
1257 | 0 | rRes.Value = xPropSet->_getPropertyValue( rRes.Name, mnParagraphIndex ); |
1258 | 0 | rRes.State = xPropSet->_getPropertyState( rRes.Name, mnParagraphIndex ); |
1259 | 0 | rRes.Handle = -1; |
1260 | 0 | } |
1261 | 0 | continue; |
1262 | 0 | } |
1263 | | // NumberingRules |
1264 | 0 | if (rRes.Name == "NumberingRules") |
1265 | 0 | { |
1266 | 0 | SfxItemSet aAttribs = rCacheTF.GetParaAttribs(GetParagraphIndex()); |
1267 | 0 | bool bVis = aAttribs.Get( EE_PARA_BULLETSTATE ).GetValue(); |
1268 | 0 | if(bVis) |
1269 | 0 | { |
1270 | 0 | rRes.Value <<= sal_Int16(-1); |
1271 | 0 | rRes.Handle = -1; |
1272 | 0 | rRes.State = PropertyState_DIRECT_VALUE; |
1273 | 0 | } |
1274 | 0 | else |
1275 | 0 | { |
1276 | | // MT IA2 TODO: Check if this is the correct replacement for ImplGetSvxCharAndParaPropertiesMap |
1277 | 0 | rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), ImplGetSvxTextPortionSvxPropertySet() ) ); |
1278 | 0 | xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) ); |
1279 | 0 | rRes.Value = xPropSet->_getPropertyValue( rRes.Name, mnParagraphIndex ); |
1280 | 0 | rRes.State = xPropSet->_getPropertyState( rRes.Name, mnParagraphIndex ); |
1281 | 0 | rRes.Handle = -1; |
1282 | 0 | } |
1283 | 0 | continue; |
1284 | 0 | } |
1285 | 0 | } |
1286 | 0 | } |
1287 | | sal_Int32 AccessibleEditableTextPara::SkipField(sal_Int32 nIndex, bool bForward) |
1288 | 0 | { |
1289 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
1290 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); |
1291 | 0 | sal_Int32 nAllFieldLen = 0; |
1292 | 0 | sal_Int32 nFoundFieldIndex = -1; |
1293 | 0 | std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex); |
1294 | 0 | sal_Int32 reeBegin=0, reeEnd=0; |
1295 | 0 | sal_Int32 j = 0; |
1296 | 0 | for (const EFieldInfo& ree : aFieldInfos) |
1297 | 0 | { |
1298 | 0 | reeBegin = ree.aPosition.nIndex + nAllFieldLen; |
1299 | 0 | reeEnd = reeBegin + ree.aCurrentText.getLength(); |
1300 | 0 | nAllFieldLen += (ree.aCurrentText.getLength() - 1); |
1301 | 0 | if (nIndex < reeBegin) |
1302 | 0 | break; |
1303 | 0 | if (!ree.pFieldItem) |
1304 | 0 | continue; |
1305 | 0 | if (nIndex < reeEnd) |
1306 | 0 | { |
1307 | 0 | if (ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL) |
1308 | 0 | { |
1309 | 0 | nFoundFieldIndex = j; |
1310 | 0 | break; |
1311 | 0 | } |
1312 | 0 | } |
1313 | 0 | j++; |
1314 | 0 | } |
1315 | 0 | if( nFoundFieldIndex >= 0 ) |
1316 | 0 | { |
1317 | 0 | if( bForward ) |
1318 | 0 | return reeEnd - 1; |
1319 | 0 | else |
1320 | 0 | return reeBegin; |
1321 | 0 | } |
1322 | 0 | return nIndex; |
1323 | 0 | } |
1324 | | void AccessibleEditableTextPara::ExtendByField( css::accessibility::TextSegment& Segment ) |
1325 | 0 | { |
1326 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
1327 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); |
1328 | 0 | std::vector<EFieldInfo> aFieldInfos = rCacheTF.GetFieldInfo(nParaIndex); |
1329 | 0 | sal_Int32 nAllFieldLen = 0; |
1330 | 0 | sal_Int32 nField = aFieldInfos.size(), nFoundFieldIndex = -1; |
1331 | 0 | sal_Int32 reeBegin=0, reeEnd=0; |
1332 | 0 | for (sal_Int32 j = 0; j < nField; ++j) |
1333 | 0 | { |
1334 | 0 | const EFieldInfo& ree = aFieldInfos[j]; |
1335 | 0 | reeBegin = ree.aPosition.nIndex + nAllFieldLen; |
1336 | 0 | reeEnd = reeBegin + ree.aCurrentText.getLength(); |
1337 | 0 | nAllFieldLen += (ree.aCurrentText.getLength() - 1); |
1338 | 0 | if( reeBegin > Segment.SegmentEnd ) |
1339 | 0 | { |
1340 | 0 | break; |
1341 | 0 | } |
1342 | 0 | if (!ree.pFieldItem) |
1343 | 0 | continue; |
1344 | 0 | if( (Segment.SegmentEnd > reeBegin && Segment.SegmentEnd <= reeEnd) || |
1345 | 0 | (Segment.SegmentStart >= reeBegin && Segment.SegmentStart < reeEnd) ) |
1346 | 0 | { |
1347 | 0 | if(ree.pFieldItem->GetField()->GetClassId() != text::textfield::Type::URL) |
1348 | 0 | { |
1349 | 0 | nFoundFieldIndex = j; |
1350 | 0 | break; |
1351 | 0 | } |
1352 | 0 | } |
1353 | 0 | } |
1354 | 0 | if( nFoundFieldIndex < 0 ) |
1355 | 0 | return; |
1356 | | |
1357 | 0 | bool bExtend = false; |
1358 | 0 | if( Segment.SegmentEnd < reeEnd ) |
1359 | 0 | { |
1360 | 0 | Segment.SegmentEnd = reeEnd; |
1361 | 0 | bExtend = true; |
1362 | 0 | } |
1363 | 0 | if( Segment.SegmentStart > reeBegin ) |
1364 | 0 | { |
1365 | 0 | Segment.SegmentStart = reeBegin; |
1366 | 0 | bExtend = true; |
1367 | 0 | } |
1368 | 0 | if( !bExtend ) |
1369 | 0 | return; |
1370 | | |
1371 | | //If there is a bullet before the field, should add the bullet length into the segment. |
1372 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex); |
1373 | 0 | sal_Int32 nBulletLen = aBulletInfo.aText.getLength(); |
1374 | 0 | if (nBulletLen > 0) |
1375 | 0 | { |
1376 | 0 | Segment.SegmentEnd += nBulletLen; |
1377 | 0 | if (nFoundFieldIndex > 0) |
1378 | 0 | Segment.SegmentStart += nBulletLen; |
1379 | 0 | Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd); |
1380 | | //After get the correct field name, should restore the offset value which don't contain the bullet. |
1381 | 0 | Segment.SegmentEnd -= nBulletLen; |
1382 | 0 | if (nFoundFieldIndex > 0) |
1383 | 0 | Segment.SegmentStart -= nBulletLen; |
1384 | 0 | } |
1385 | 0 | else |
1386 | 0 | Segment.SegmentText = GetTextRange(Segment.SegmentStart, Segment.SegmentEnd); |
1387 | 0 | } |
1388 | | |
1389 | | css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtIndex( sal_Int32 nIndex, sal_Int16 aTextType ) |
1390 | 0 | { |
1391 | 0 | SolarMutexGuard aGuard; |
1392 | |
|
1393 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1394 | 0 | "AccessibleEditableTextPara::getTextAtIndex: paragraph index value overflow"); |
1395 | |
|
1396 | 0 | css::accessibility::TextSegment aResult; |
1397 | 0 | aResult.SegmentStart = -1; |
1398 | 0 | aResult.SegmentEnd = -1; |
1399 | |
|
1400 | 0 | switch( aTextType ) |
1401 | 0 | { |
1402 | 0 | case AccessibleTextType::CHARACTER: |
1403 | 0 | case AccessibleTextType::WORD: |
1404 | 0 | { |
1405 | 0 | aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); |
1406 | 0 | ExtendByField( aResult ); |
1407 | 0 | break; |
1408 | 0 | } |
1409 | | // Not yet handled by OCommonAccessibleText. Missing |
1410 | | // implGetAttributeRunBoundary() method there |
1411 | 0 | case AccessibleTextType::ATTRIBUTE_RUN: |
1412 | 0 | { |
1413 | 0 | const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() ); |
1414 | |
|
1415 | 0 | if( nIndex == nTextLen ) |
1416 | 0 | { |
1417 | | // #i17014# Special-casing one-behind-the-end character |
1418 | 0 | aResult.SegmentStart = aResult.SegmentEnd = nTextLen; |
1419 | 0 | } |
1420 | 0 | else |
1421 | 0 | { |
1422 | 0 | sal_Int32 nStartIndex, nEndIndex; |
1423 | | //For the bullet paragraph, the bullet string is ignored for IAText::attributes() function. |
1424 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1425 | | // MT IA2: Not used? sal_Int32 nBulletLen = 0; |
1426 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(GetParagraphIndex()); |
1427 | 0 | if (aBulletInfo.bVisible) |
1428 | 0 | nIndex += aBulletInfo.aText.getLength(); |
1429 | 0 | if (nIndex != 0 && nIndex >= getCharacterCount()) |
1430 | 0 | nIndex = getCharacterCount()-1; |
1431 | 0 | CheckPosition(nIndex); |
1432 | 0 | if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) |
1433 | 0 | { |
1434 | 0 | aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); |
1435 | 0 | if (aBulletInfo.bVisible) |
1436 | 0 | { |
1437 | 0 | nStartIndex -= aBulletInfo.aText.getLength(); |
1438 | 0 | nEndIndex -= aBulletInfo.aText.getLength(); |
1439 | 0 | } |
1440 | 0 | aResult.SegmentStart = nStartIndex; |
1441 | 0 | aResult.SegmentEnd = nEndIndex; |
1442 | 0 | } |
1443 | 0 | } |
1444 | 0 | break; |
1445 | 0 | } |
1446 | 0 | case AccessibleTextType::LINE: |
1447 | 0 | { |
1448 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1449 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
1450 | 0 | CheckPosition(nIndex); |
1451 | 0 | if (nIndex != 0 && nIndex == getCharacterCount()) |
1452 | 0 | --nIndex; |
1453 | 0 | sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex ); |
1454 | 0 | sal_Int32 nCurIndex; |
1455 | | //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line, |
1456 | | //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed |
1457 | | //by the IAText::attributes(). So here must do special support for bullet line. |
1458 | 0 | sal_Int32 nBulletLen = 0; |
1459 | 0 | for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) |
1460 | 0 | { |
1461 | 0 | if (nLine == 0) |
1462 | 0 | { |
1463 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo( nParaIndex ); |
1464 | 0 | if (aBulletInfo.bVisible) |
1465 | 0 | { |
1466 | | //in bullet or numbering; |
1467 | 0 | nBulletLen = aBulletInfo.aText.getLength(); |
1468 | 0 | } |
1469 | 0 | } |
1470 | 0 | sal_Int32 nLineLen = rCacheTF.GetLineLen(nParaIndex, nLine); |
1471 | 0 | if (nLine == 0) |
1472 | 0 | nCurIndex += nLineLen - nBulletLen; |
1473 | 0 | else |
1474 | 0 | nCurIndex += nLineLen; |
1475 | 0 | if( nCurIndex > nIndex ) |
1476 | 0 | { |
1477 | 0 | if (nLine ==0) |
1478 | 0 | { |
1479 | 0 | aResult.SegmentStart = 0; |
1480 | 0 | aResult.SegmentEnd = nCurIndex; |
1481 | 0 | aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen); |
1482 | 0 | break; |
1483 | 0 | } |
1484 | 0 | else |
1485 | 0 | { |
1486 | 0 | aResult.SegmentStart = nCurIndex - nLineLen; |
1487 | 0 | aResult.SegmentEnd = nCurIndex; |
1488 | | //aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd ); |
1489 | 0 | aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen); |
1490 | 0 | break; |
1491 | 0 | } |
1492 | 0 | } |
1493 | 0 | } |
1494 | 0 | break; |
1495 | 0 | } |
1496 | 0 | default: |
1497 | 0 | aResult = OCommonAccessibleText::getTextAtIndex( nIndex, aTextType ); |
1498 | 0 | break; |
1499 | 0 | } /* end of switch( aTextType ) */ |
1500 | | |
1501 | 0 | return aResult; |
1502 | 0 | } |
1503 | | |
1504 | | css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBeforeIndex( sal_Int32 nIndex, sal_Int16 aTextType ) |
1505 | 0 | { |
1506 | 0 | SolarMutexGuard aGuard; |
1507 | |
|
1508 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1509 | 0 | "AccessibleEditableTextPara::getTextBeforeIndex: paragraph index value overflow"); |
1510 | |
|
1511 | 0 | css::accessibility::TextSegment aResult; |
1512 | 0 | aResult.SegmentStart = -1; |
1513 | 0 | aResult.SegmentEnd = -1; |
1514 | 0 | i18n::Boundary aBoundary; |
1515 | 0 | switch( aTextType ) |
1516 | 0 | { |
1517 | | // Not yet handled by OCommonAccessibleText. Missing |
1518 | | // implGetAttributeRunBoundary() method there |
1519 | 0 | case AccessibleTextType::ATTRIBUTE_RUN: |
1520 | 0 | { |
1521 | 0 | const sal_Int32 nTextLen = GetTextForwarder().GetTextLen( GetParagraphIndex() ); |
1522 | 0 | sal_Int32 nStartIndex, nEndIndex; |
1523 | |
|
1524 | 0 | if( nIndex == nTextLen ) |
1525 | 0 | { |
1526 | | // #i17014# Special-casing one-behind-the-end character |
1527 | 0 | if( nIndex > 0 && |
1528 | 0 | GetAttributeRun(nStartIndex, nEndIndex, nIndex-1) ) |
1529 | 0 | { |
1530 | 0 | aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); |
1531 | 0 | aResult.SegmentStart = nStartIndex; |
1532 | 0 | aResult.SegmentEnd = nEndIndex; |
1533 | 0 | } |
1534 | 0 | } |
1535 | 0 | else |
1536 | 0 | { |
1537 | 0 | if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) |
1538 | 0 | { |
1539 | | // already at the left border? If not, query |
1540 | | // one index further left |
1541 | 0 | if( nStartIndex > 0 && |
1542 | 0 | GetAttributeRun(nStartIndex, nEndIndex, nStartIndex-1) ) |
1543 | 0 | { |
1544 | 0 | aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); |
1545 | 0 | aResult.SegmentStart = nStartIndex; |
1546 | 0 | aResult.SegmentEnd = nEndIndex; |
1547 | 0 | } |
1548 | 0 | } |
1549 | 0 | } |
1550 | 0 | break; |
1551 | 0 | } |
1552 | 0 | case AccessibleTextType::LINE: |
1553 | 0 | { |
1554 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1555 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
1556 | |
|
1557 | 0 | CheckPosition(nIndex); |
1558 | |
|
1559 | 0 | sal_Int32 nLine, nLineCount=rCacheTF.GetLineCount( nParaIndex ); |
1560 | | //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line, |
1561 | | //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed |
1562 | | //by the IAText::attributes(). So here must do special support for bullet line. |
1563 | 0 | sal_Int32 nCurIndex=0, nLastIndex=0, nCurLineLen=0; |
1564 | 0 | sal_Int32 nLastLineLen = 0, nBulletLen = 0; |
1565 | | // get the line before the line the index points into |
1566 | 0 | for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) |
1567 | 0 | { |
1568 | 0 | nLastIndex = nCurIndex; |
1569 | 0 | if (nLine == 0) |
1570 | 0 | { |
1571 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex); |
1572 | 0 | if (aBulletInfo.bVisible) |
1573 | 0 | { |
1574 | | //in bullet or numbering; |
1575 | 0 | nBulletLen = aBulletInfo.aText.getLength(); |
1576 | 0 | } |
1577 | 0 | } |
1578 | 0 | if (nLine == 1) |
1579 | 0 | nLastLineLen = nCurLineLen - nBulletLen; |
1580 | 0 | else |
1581 | 0 | nLastLineLen = nCurLineLen; |
1582 | 0 | nCurLineLen = rCacheTF.GetLineLen( nParaIndex, nLine); |
1583 | | //nCurIndex += nCurLineLen; |
1584 | 0 | if (nLine == 0) |
1585 | 0 | nCurIndex += nCurLineLen - nBulletLen; |
1586 | 0 | else |
1587 | 0 | nCurIndex += nCurLineLen; |
1588 | | |
1589 | | //if( nCurIndex > nIndex && |
1590 | | //nLastIndex > nCurLineLen ) |
1591 | 0 | if (nCurIndex > nIndex) |
1592 | 0 | { |
1593 | 0 | if (nLine == 0) |
1594 | 0 | { |
1595 | 0 | break; |
1596 | 0 | } |
1597 | 0 | else if (nLine == 1) |
1598 | 0 | { |
1599 | 0 | aResult.SegmentStart = 0; |
1600 | 0 | aResult.SegmentEnd = nLastIndex; |
1601 | 0 | aResult.SegmentText = GetTextRange( aResult.SegmentStart, aResult.SegmentEnd + nBulletLen); |
1602 | 0 | break; |
1603 | 0 | } |
1604 | 0 | else |
1605 | 0 | { |
1606 | | //aResult.SegmentStart = nLastIndex - nCurLineLen; |
1607 | 0 | aResult.SegmentStart = nLastIndex - nLastLineLen; |
1608 | 0 | aResult.SegmentEnd = nLastIndex; |
1609 | 0 | aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen); |
1610 | 0 | break; |
1611 | 0 | } |
1612 | 0 | } |
1613 | 0 | } |
1614 | |
|
1615 | 0 | break; |
1616 | 0 | } |
1617 | 0 | case AccessibleTextType::WORD: |
1618 | 0 | { |
1619 | 0 | nIndex = SkipField( nIndex, false); |
1620 | 0 | OUString sText( implGetText() ); |
1621 | 0 | sal_Int32 nLength = sText.getLength(); |
1622 | | |
1623 | | // get word at index |
1624 | 0 | implGetWordBoundary( sText, aBoundary, nIndex ); |
1625 | | |
1626 | | |
1627 | | //sal_Int32 curWordStart = aBoundary.startPos; |
1628 | | //sal_Int32 preWordStart = curWordStart; |
1629 | 0 | sal_Int32 curWordStart , preWordStart; |
1630 | 0 | if( aBoundary.startPos == -1 || aBoundary.startPos > nIndex) |
1631 | 0 | curWordStart = preWordStart = nIndex; |
1632 | 0 | else |
1633 | 0 | curWordStart = preWordStart = aBoundary.startPos; |
1634 | | |
1635 | | // get previous word |
1636 | |
|
1637 | 0 | bool bWord = false; |
1638 | | |
1639 | | //while ( preWordStart > 0 && aBoundary.startPos == curWordStart) |
1640 | 0 | while ( (preWordStart >= 0 && !bWord ) || ( aBoundary.endPos > curWordStart ) ) |
1641 | 0 | { |
1642 | 0 | preWordStart--; |
1643 | 0 | bWord = implGetWordBoundary( sText, aBoundary, preWordStart ); |
1644 | 0 | } |
1645 | 0 | if ( bWord && implIsValidBoundary( aBoundary, nLength ) ) |
1646 | 0 | { |
1647 | 0 | aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); |
1648 | 0 | aResult.SegmentStart = aBoundary.startPos; |
1649 | 0 | aResult.SegmentEnd = aBoundary.endPos; |
1650 | 0 | ExtendByField( aResult ); |
1651 | 0 | } |
1652 | 0 | } |
1653 | 0 | break; |
1654 | 0 | case AccessibleTextType::CHARACTER: |
1655 | 0 | { |
1656 | 0 | nIndex = SkipField( nIndex, false); |
1657 | 0 | aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); |
1658 | 0 | ExtendByField( aResult ); |
1659 | 0 | break; |
1660 | 0 | } |
1661 | 0 | default: |
1662 | 0 | aResult = OCommonAccessibleText::getTextBeforeIndex( nIndex, aTextType ); |
1663 | 0 | break; |
1664 | 0 | } /* end of switch( aTextType ) */ |
1665 | | |
1666 | 0 | return aResult; |
1667 | 0 | } |
1668 | | |
1669 | | css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextBehindIndex( sal_Int32 nIndex, sal_Int16 aTextType ) |
1670 | 0 | { |
1671 | 0 | SolarMutexGuard aGuard; |
1672 | |
|
1673 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1674 | 0 | "AccessibleEditableTextPara::getTextBehindIndex: paragraph index value overflow"); |
1675 | |
|
1676 | 0 | css::accessibility::TextSegment aResult; |
1677 | 0 | aResult.SegmentStart = -1; |
1678 | 0 | aResult.SegmentEnd = -1; |
1679 | 0 | i18n::Boundary aBoundary; |
1680 | 0 | switch( aTextType ) |
1681 | 0 | { |
1682 | 0 | case AccessibleTextType::ATTRIBUTE_RUN: |
1683 | 0 | { |
1684 | 0 | sal_Int32 nStartIndex, nEndIndex; |
1685 | |
|
1686 | 0 | if( GetAttributeRun(nStartIndex, nEndIndex, nIndex) ) |
1687 | 0 | { |
1688 | | // already at the right border? |
1689 | 0 | if( nEndIndex < GetTextLen() ) |
1690 | 0 | { |
1691 | 0 | if( GetAttributeRun(nStartIndex, nEndIndex, nEndIndex) ) |
1692 | 0 | { |
1693 | 0 | aResult.SegmentText = GetTextRange(nStartIndex, nEndIndex); |
1694 | 0 | aResult.SegmentStart = nStartIndex; |
1695 | 0 | aResult.SegmentEnd = nEndIndex; |
1696 | 0 | } |
1697 | 0 | } |
1698 | 0 | } |
1699 | 0 | break; |
1700 | 0 | } |
1701 | | |
1702 | 0 | case AccessibleTextType::LINE: |
1703 | 0 | { |
1704 | 0 | SvxTextForwarder& rCacheTF = GetTextForwarder(); |
1705 | 0 | sal_Int32 nParaIndex = GetParagraphIndex(); |
1706 | |
|
1707 | 0 | CheckPosition(nIndex); |
1708 | |
|
1709 | 0 | sal_Int32 nLine, nLineCount = rCacheTF.GetLineCount( nParaIndex ); |
1710 | 0 | sal_Int32 nCurIndex; |
1711 | | //the problem is that rCacheTF.GetLineLen() will include the bullet length. But for the bullet line, |
1712 | | //the text value doesn't contain the bullet characters. all of the bullet and numbering info are exposed |
1713 | | //by the IAText::attributes(). So here must do special support for bullet line. |
1714 | 0 | sal_Int32 nBulletLen = 0; |
1715 | | // get the line after the line the index points into |
1716 | 0 | for( nLine=0, nCurIndex=0; nLine<nLineCount; ++nLine ) |
1717 | 0 | { |
1718 | 0 | if (nLine == 0) |
1719 | 0 | { |
1720 | 0 | EBulletInfo aBulletInfo = rCacheTF.GetBulletInfo(nParaIndex); |
1721 | 0 | if (aBulletInfo.bVisible) |
1722 | 0 | { |
1723 | | //in bullet or numbering; |
1724 | 0 | nBulletLen = aBulletInfo.aText.getLength(); |
1725 | 0 | } |
1726 | 0 | } |
1727 | 0 | sal_Int32 nLineLen = rCacheTF.GetLineLen( nParaIndex, nLine); |
1728 | |
|
1729 | 0 | if (nLine == 0) |
1730 | 0 | nCurIndex += nLineLen - nBulletLen; |
1731 | 0 | else |
1732 | 0 | nCurIndex += nLineLen; |
1733 | |
|
1734 | 0 | if( nCurIndex > nIndex && |
1735 | 0 | nLine < nLineCount-1 ) |
1736 | 0 | { |
1737 | 0 | aResult.SegmentStart = nCurIndex; |
1738 | 0 | aResult.SegmentEnd = nCurIndex + rCacheTF.GetLineLen( nParaIndex, nLine+1); |
1739 | 0 | aResult.SegmentText = GetTextRange( aResult.SegmentStart + nBulletLen, aResult.SegmentEnd + nBulletLen); |
1740 | 0 | break; |
1741 | 0 | } |
1742 | 0 | } |
1743 | |
|
1744 | 0 | break; |
1745 | 0 | } |
1746 | 0 | case AccessibleTextType::WORD: |
1747 | 0 | { |
1748 | 0 | nIndex = SkipField( nIndex, true); |
1749 | 0 | OUString sText( implGetText() ); |
1750 | 0 | sal_Int32 nLength = sText.getLength(); |
1751 | | |
1752 | | // get word at index |
1753 | 0 | bool bWord = implGetWordBoundary( sText, aBoundary, nIndex ); |
1754 | | |
1755 | | // real current world |
1756 | 0 | sal_Int32 nextWord = nIndex; |
1757 | | //if( nIndex >= aBoundary.startPos && nIndex <= aBoundary.endPos ) |
1758 | 0 | if( nIndex <= aBoundary.endPos ) |
1759 | 0 | { |
1760 | 0 | nextWord = aBoundary.endPos; |
1761 | 0 | if (nextWord < sText.getLength() && sText[nextWord] == u' ') nextWord++; |
1762 | 0 | bWord = implGetWordBoundary( sText, aBoundary, nextWord ); |
1763 | 0 | } |
1764 | |
|
1765 | 0 | if ( bWord && implIsValidBoundary( aBoundary, nLength ) ) |
1766 | 0 | { |
1767 | 0 | aResult.SegmentText = sText.copy( aBoundary.startPos, aBoundary.endPos - aBoundary.startPos ); |
1768 | 0 | aResult.SegmentStart = aBoundary.startPos; |
1769 | 0 | aResult.SegmentEnd = aBoundary.endPos; |
1770 | | |
1771 | | // If the end position of aBoundary is inside a field, extend the result to the end of the field |
1772 | |
|
1773 | 0 | ExtendByField( aResult ); |
1774 | 0 | } |
1775 | 0 | } |
1776 | 0 | break; |
1777 | | |
1778 | 0 | case AccessibleTextType::CHARACTER: |
1779 | 0 | { |
1780 | 0 | nIndex = SkipField( nIndex, true); |
1781 | 0 | aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); |
1782 | 0 | ExtendByField( aResult ); |
1783 | 0 | break; |
1784 | 0 | } |
1785 | 0 | default: |
1786 | 0 | aResult = OCommonAccessibleText::getTextBehindIndex( nIndex, aTextType ); |
1787 | 0 | break; |
1788 | 0 | } /* end of switch( aTextType ) */ |
1789 | | |
1790 | 0 | return aResult; |
1791 | 0 | } |
1792 | | |
1793 | | sal_Bool SAL_CALL AccessibleEditableTextPara::copyText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
1794 | 0 | { |
1795 | 0 | SolarMutexGuard aGuard; |
1796 | |
|
1797 | 0 | try |
1798 | 0 | { |
1799 | 0 | SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true ); |
1800 | 0 | GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1801 | |
|
1802 | 0 | bool aRetVal; |
1803 | |
|
1804 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1805 | 0 | "AccessibleEditableTextPara::copyText: index value overflow"); |
1806 | |
|
1807 | 0 | CheckRange(nStartIndex, nEndIndex); |
1808 | | |
1809 | | //Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1810 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1811 | | // save current selection |
1812 | 0 | ESelection aOldSelection; |
1813 | |
|
1814 | 0 | rCacheVF.GetSelection( aOldSelection ); |
1815 | | //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); |
1816 | 0 | rCacheVF.SetSelection( MakeSelection(nStartIndex + nBulletLen, nEndIndex + nBulletLen) ); |
1817 | 0 | aRetVal = rCacheVF.Copy(); |
1818 | 0 | rCacheVF.SetSelection( aOldSelection ); // restore |
1819 | |
|
1820 | 0 | return aRetVal; |
1821 | 0 | } |
1822 | 0 | catch (const uno::RuntimeException&) |
1823 | 0 | { |
1824 | 0 | return false; |
1825 | 0 | } |
1826 | 0 | } |
1827 | | |
1828 | | sal_Bool SAL_CALL AccessibleEditableTextPara::scrollSubstringTo( sal_Int32, sal_Int32, AccessibleScrollType ) |
1829 | 0 | { |
1830 | 0 | return false; |
1831 | 0 | } |
1832 | | |
1833 | | // XAccessibleEditableText |
1834 | | sal_Bool SAL_CALL AccessibleEditableTextPara::cutText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
1835 | 0 | { |
1836 | |
|
1837 | 0 | SolarMutexGuard aGuard; |
1838 | |
|
1839 | 0 | try |
1840 | 0 | { |
1841 | 0 | SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true ); |
1842 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1843 | |
|
1844 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1845 | 0 | "AccessibleEditableTextPara::cutText: index value overflow"); |
1846 | |
|
1847 | 0 | CheckRange(nStartIndex, nEndIndex); |
1848 | | |
1849 | | // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1850 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1851 | 0 | ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen); |
1852 | | //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) |
1853 | 0 | if( !rCacheTF.IsEditable( aSelection ) ) |
1854 | 0 | return false; // non-editable area selected |
1855 | | |
1856 | | // don't save selection, might become invalid after cut! |
1857 | | //rCacheVF.SetSelection( MakeSelection(nStartIndex, nEndIndex) ); |
1858 | 0 | rCacheVF.SetSelection( aSelection ); |
1859 | |
|
1860 | 0 | return rCacheVF.Cut(); |
1861 | 0 | } |
1862 | 0 | catch (const uno::RuntimeException&) |
1863 | 0 | { |
1864 | 0 | return false; |
1865 | 0 | } |
1866 | 0 | } |
1867 | | |
1868 | | sal_Bool SAL_CALL AccessibleEditableTextPara::pasteText( sal_Int32 nIndex ) |
1869 | 0 | { |
1870 | |
|
1871 | 0 | SolarMutexGuard aGuard; |
1872 | |
|
1873 | 0 | try |
1874 | 0 | { |
1875 | 0 | SvxEditViewForwarder& rCacheVF = GetEditViewForwarder( true ); |
1876 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1877 | |
|
1878 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1879 | 0 | "AccessibleEditableTextPara::pasteText: index value overflow"); |
1880 | |
|
1881 | 0 | CheckPosition(nIndex); |
1882 | | |
1883 | | // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1884 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1885 | 0 | if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) ) |
1886 | 0 | return false; // non-editable area selected |
1887 | | |
1888 | | // #104400# set empty selection (=> cursor) to given index |
1889 | | //rCacheVF.SetSelection( MakeCursor(nIndex) ); |
1890 | 0 | rCacheVF.SetSelection( MakeCursor(nIndex + nBulletLen) ); |
1891 | |
|
1892 | 0 | return rCacheVF.Paste(); |
1893 | 0 | } |
1894 | 0 | catch (const uno::RuntimeException&) |
1895 | 0 | { |
1896 | 0 | return false; |
1897 | 0 | } |
1898 | 0 | } |
1899 | | |
1900 | | sal_Bool SAL_CALL AccessibleEditableTextPara::deleteText( sal_Int32 nStartIndex, sal_Int32 nEndIndex ) |
1901 | 0 | { |
1902 | |
|
1903 | 0 | SolarMutexGuard aGuard; |
1904 | |
|
1905 | 0 | try |
1906 | 0 | { |
1907 | | // #102710# Request edit view when doing changes |
1908 | | // AccessibleEmptyEditSource relies on this behaviour |
1909 | 0 | GetEditViewForwarder( true ); |
1910 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1911 | |
|
1912 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1913 | 0 | "AccessibleEditableTextPara::deleteText: index value overflow"); |
1914 | |
|
1915 | 0 | CheckRange(nStartIndex, nEndIndex); |
1916 | | |
1917 | | // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1918 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1919 | 0 | ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen); |
1920 | | |
1921 | | //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) |
1922 | 0 | if( !rCacheTF.IsEditable( aSelection ) ) |
1923 | 0 | return false; // non-editable area selected |
1924 | | |
1925 | | //sal_Bool bRet = rCacheTF.Delete( MakeSelection(nStartIndex, nEndIndex) ); |
1926 | 0 | bool bRet = rCacheTF.Delete( aSelection ); |
1927 | |
|
1928 | 0 | GetEditSource().UpdateData(); |
1929 | |
|
1930 | 0 | return bRet; |
1931 | 0 | } |
1932 | 0 | catch (const uno::RuntimeException&) |
1933 | 0 | { |
1934 | 0 | return false; |
1935 | 0 | } |
1936 | 0 | } |
1937 | | |
1938 | | sal_Bool SAL_CALL AccessibleEditableTextPara::insertText( const OUString& sText, sal_Int32 nIndex ) |
1939 | 0 | { |
1940 | |
|
1941 | 0 | SolarMutexGuard aGuard; |
1942 | |
|
1943 | 0 | try |
1944 | 0 | { |
1945 | | // #102710# Request edit view when doing changes |
1946 | | // AccessibleEmptyEditSource relies on this behaviour |
1947 | 0 | GetEditViewForwarder( true ); |
1948 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1949 | |
|
1950 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1951 | 0 | "AccessibleEditableTextPara::insertText: index value overflow"); |
1952 | |
|
1953 | 0 | CheckPosition(nIndex); |
1954 | | |
1955 | | // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1956 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1957 | 0 | if( !rCacheTF.IsEditable( MakeSelection(nIndex + nBulletLen) ) ) |
1958 | 0 | return false; // non-editable area selected |
1959 | | |
1960 | | // #104400# insert given text at empty selection (=> cursor) |
1961 | 0 | bool bRet = rCacheTF.InsertText( sText, MakeCursor(nIndex + nBulletLen) ); |
1962 | |
|
1963 | 0 | rCacheTF.QuickFormatDoc(); |
1964 | 0 | GetEditSource().UpdateData(); |
1965 | |
|
1966 | 0 | return bRet; |
1967 | 0 | } |
1968 | 0 | catch (const uno::RuntimeException&) |
1969 | 0 | { |
1970 | 0 | return false; |
1971 | 0 | } |
1972 | 0 | } |
1973 | | |
1974 | | sal_Bool SAL_CALL AccessibleEditableTextPara::replaceText( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const OUString& sReplacement ) |
1975 | 0 | { |
1976 | |
|
1977 | 0 | SolarMutexGuard aGuard; |
1978 | |
|
1979 | 0 | try |
1980 | 0 | { |
1981 | | // #102710# Request edit view when doing changes |
1982 | | // AccessibleEmptyEditSource relies on this behaviour |
1983 | 0 | GetEditViewForwarder( true ); |
1984 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
1985 | |
|
1986 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
1987 | 0 | "AccessibleEditableTextPara::replaceText: index value overflow"); |
1988 | |
|
1989 | 0 | CheckRange(nStartIndex, nEndIndex); |
1990 | | |
1991 | | // Because bullet may occupy one or more characters, the TextAdapter will include bullet to calculate the selection. Add offset to handle bullet |
1992 | 0 | const sal_Int32 nBulletLen = GetBulletTextLength(); |
1993 | 0 | ESelection aSelection = MakeSelection (nStartIndex + nBulletLen, nEndIndex + nBulletLen); |
1994 | | |
1995 | | //if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) |
1996 | 0 | if( !rCacheTF.IsEditable( aSelection ) ) |
1997 | 0 | return false; // non-editable area selected |
1998 | | |
1999 | | // insert given text into given range => replace |
2000 | | //sal_Bool bRet = rCacheTF.InsertText( sReplacement, MakeSelection(nStartIndex, nEndIndex) ); |
2001 | 0 | bool bRet = rCacheTF.InsertText( sReplacement, aSelection ); |
2002 | |
|
2003 | 0 | rCacheTF.QuickFormatDoc(); |
2004 | 0 | GetEditSource().UpdateData(); |
2005 | |
|
2006 | 0 | return bRet; |
2007 | 0 | } |
2008 | 0 | catch (const uno::RuntimeException&) |
2009 | 0 | { |
2010 | 0 | return false; |
2011 | 0 | } |
2012 | 0 | } |
2013 | | |
2014 | | sal_Bool SAL_CALL AccessibleEditableTextPara::setAttributes( sal_Int32 nStartIndex, sal_Int32 nEndIndex, const uno::Sequence< beans::PropertyValue >& aAttributeSet ) |
2015 | 0 | { |
2016 | |
|
2017 | 0 | SolarMutexGuard aGuard; |
2018 | |
|
2019 | 0 | try |
2020 | 0 | { |
2021 | | // #102710# Request edit view when doing changes |
2022 | | // AccessibleEmptyEditSource relies on this behaviour |
2023 | 0 | GetEditViewForwarder( true ); |
2024 | 0 | SvxAccessibleTextAdapter& rCacheTF = GetTextForwarder(); // MUST be after GetEditViewForwarder(), see method docs |
2025 | 0 | sal_Int32 nPara = GetParagraphIndex(); |
2026 | |
|
2027 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
2028 | 0 | "AccessibleEditableTextPara::setAttributes: index value overflow"); |
2029 | |
|
2030 | 0 | CheckRange(nStartIndex, nEndIndex); |
2031 | |
|
2032 | 0 | if( !rCacheTF.IsEditable( MakeSelection(nStartIndex, nEndIndex) ) ) |
2033 | 0 | return false; // non-editable area selected |
2034 | | |
2035 | | // do the indices span the whole paragraph? Then use the outliner map |
2036 | | // TODO: hold it as a member? |
2037 | 0 | rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), |
2038 | 0 | 0 == nStartIndex && |
2039 | 0 | rCacheTF.GetTextLen(nPara) == nEndIndex ? |
2040 | 0 | ImplGetSvxUnoOutlinerTextCursorSvxPropertySet() : |
2041 | 0 | ImplGetSvxTextPortionSvxPropertySet() ) ); |
2042 | |
|
2043 | 0 | xPropSet->SetSelection( MakeSelection(nStartIndex, nEndIndex) ); |
2044 | | |
2045 | | // convert from PropertyValue to Any |
2046 | 0 | for(const beans::PropertyValue& rProp : aAttributeSet) |
2047 | 0 | { |
2048 | 0 | try |
2049 | 0 | { |
2050 | 0 | xPropSet->setPropertyValue(rProp.Name, rProp.Value); |
2051 | 0 | } |
2052 | 0 | catch (const uno::Exception&) |
2053 | 0 | { |
2054 | 0 | TOOLS_WARN_EXCEPTION( "dbaccess", "AccessibleEditableTextPara::setAttributes exception in setPropertyValue"); |
2055 | 0 | } |
2056 | 0 | } |
2057 | | |
2058 | 0 | rCacheTF.QuickFormatDoc(); |
2059 | 0 | GetEditSource().UpdateData(); |
2060 | |
|
2061 | 0 | return true; |
2062 | 0 | } |
2063 | 0 | catch (const uno::RuntimeException&) |
2064 | 0 | { |
2065 | 0 | return false; |
2066 | 0 | } |
2067 | 0 | } |
2068 | | |
2069 | | sal_Bool SAL_CALL AccessibleEditableTextPara::setText( const OUString& sText ) |
2070 | 0 | { |
2071 | |
|
2072 | 0 | SolarMutexGuard aGuard; |
2073 | |
|
2074 | 0 | return replaceText(0, getCharacterCount(), sText); |
2075 | 0 | } |
2076 | | |
2077 | | // XAccessibleTextAttributes |
2078 | | uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getDefaultAttributes( |
2079 | | const uno::Sequence< OUString >& rRequestedAttributes ) |
2080 | 0 | { |
2081 | 0 | SolarMutexGuard aGuard; |
2082 | |
|
2083 | 0 | GetTextForwarder(); |
2084 | |
|
2085 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
2086 | 0 | "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); |
2087 | | |
2088 | | // get XPropertySetInfo for paragraph attributes and |
2089 | | // character attributes that span all the paragraphs text. |
2090 | 0 | rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), |
2091 | 0 | ImplGetSvxCharAndParaPropertiesSet() ) ); |
2092 | 0 | xPropSet->SetSelection( MakeSelection( 0, GetTextLen() ) ); |
2093 | 0 | uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); |
2094 | 0 | if (!xPropSetInfo.is()) |
2095 | 0 | throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak()); |
2096 | | |
2097 | | // build sequence of available properties to check |
2098 | 0 | uno::Sequence< beans::Property > aProperties; |
2099 | 0 | if (const sal_Int32 nLenReqAttr = rRequestedAttributes.getLength()) |
2100 | 0 | { |
2101 | 0 | aProperties.realloc( nLenReqAttr ); |
2102 | 0 | beans::Property *pProperties = aProperties.getArray(); |
2103 | 0 | sal_Int32 nCurLen = 0; |
2104 | 0 | for (const OUString& rRequestedAttribute : rRequestedAttributes) |
2105 | 0 | { |
2106 | 0 | beans::Property aProp; |
2107 | 0 | try |
2108 | 0 | { |
2109 | 0 | aProp = xPropSetInfo->getPropertyByName( rRequestedAttribute ); |
2110 | 0 | } |
2111 | 0 | catch (const beans::UnknownPropertyException&) |
2112 | 0 | { |
2113 | 0 | continue; |
2114 | 0 | } |
2115 | 0 | pProperties[nCurLen++] = std::move(aProp); |
2116 | 0 | } |
2117 | 0 | aProperties.realloc( nCurLen ); |
2118 | 0 | } |
2119 | 0 | else |
2120 | 0 | aProperties = xPropSetInfo->getProperties(); |
2121 | | |
2122 | | // build resulting sequence |
2123 | 0 | uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() ); |
2124 | 0 | beans::PropertyValue* pOutSequence = aOutSequence.getArray(); |
2125 | 0 | sal_Int32 nOutLen = 0; |
2126 | 0 | for (const beans::Property& rProperty : aProperties) |
2127 | 0 | { |
2128 | | // calling implementation functions: |
2129 | | // _getPropertyState and _getPropertyValue (see below) to provide |
2130 | | // the proper paragraph number when retrieving paragraph attributes |
2131 | 0 | PropertyState eState = xPropSet->_getPropertyState( rProperty.Name, mnParagraphIndex ); |
2132 | 0 | if ( eState == PropertyState_AMBIGUOUS_VALUE ) |
2133 | 0 | { |
2134 | 0 | OSL_FAIL( "ambiguous property value encountered" ); |
2135 | 0 | } |
2136 | | |
2137 | | //if (eState == PropertyState_DIRECT_VALUE) |
2138 | | // per definition all paragraph properties and all character |
2139 | | // properties spanning the whole paragraph should be returned |
2140 | | // and declared as default value |
2141 | 0 | { |
2142 | 0 | pOutSequence->Name = rProperty.Name; |
2143 | 0 | pOutSequence->Handle = rProperty.Handle; |
2144 | 0 | pOutSequence->Value = xPropSet->_getPropertyValue( rProperty.Name, mnParagraphIndex ); |
2145 | 0 | pOutSequence->State = PropertyState_DEFAULT_VALUE; |
2146 | |
|
2147 | 0 | ++pOutSequence; |
2148 | 0 | ++nOutLen; |
2149 | 0 | } |
2150 | 0 | } |
2151 | 0 | aOutSequence.realloc( nOutLen ); |
2152 | |
|
2153 | 0 | return aOutSequence; |
2154 | 0 | } |
2155 | | |
2156 | | |
2157 | | uno::Sequence< beans::PropertyValue > SAL_CALL AccessibleEditableTextPara::getRunAttributes( |
2158 | | sal_Int32 nIndex, |
2159 | | const uno::Sequence< OUString >& rRequestedAttributes ) |
2160 | 0 | { |
2161 | |
|
2162 | 0 | SolarMutexGuard aGuard; |
2163 | |
|
2164 | 0 | GetTextForwarder(); |
2165 | |
|
2166 | 0 | DBG_ASSERT(GetParagraphIndex() >= 0, |
2167 | 0 | "AccessibleEditableTextPara::getCharacterAttributes: index value overflow"); |
2168 | |
|
2169 | 0 | if( getCharacterCount() > 0 ) |
2170 | 0 | CheckIndex(nIndex); |
2171 | 0 | else |
2172 | 0 | CheckPosition(nIndex); |
2173 | |
|
2174 | 0 | rtl::Reference< SvxAccessibleTextPropertySet > xPropSet( new SvxAccessibleTextPropertySet( &GetEditSource(), |
2175 | 0 | ImplGetSvxCharAndParaPropertiesSet() ) ); |
2176 | 0 | xPropSet->SetSelection( MakeSelection( nIndex ) ); |
2177 | 0 | uno::Reference< beans::XPropertySetInfo > xPropSetInfo = xPropSet->getPropertySetInfo(); |
2178 | 0 | if (!xPropSetInfo.is()) |
2179 | 0 | throw uno::RuntimeException(u"Cannot query XPropertySetInfo"_ustr, getXWeak()); |
2180 | | |
2181 | | // build sequence of available properties to check |
2182 | 0 | uno::Sequence< beans::Property > aProperties; |
2183 | 0 | if (const sal_Int32 nLenReqAttr = rRequestedAttributes.getLength()) |
2184 | 0 | { |
2185 | 0 | aProperties.realloc( nLenReqAttr ); |
2186 | 0 | beans::Property *pProperties = aProperties.getArray(); |
2187 | 0 | sal_Int32 nCurLen = 0; |
2188 | 0 | for (const OUString& rRequestedAttribute : rRequestedAttributes) |
2189 | 0 | { |
2190 | 0 | beans::Property aProp; |
2191 | 0 | try |
2192 | 0 | { |
2193 | 0 | aProp = xPropSetInfo->getPropertyByName( rRequestedAttribute ); |
2194 | 0 | } |
2195 | 0 | catch (const beans::UnknownPropertyException&) |
2196 | 0 | { |
2197 | 0 | continue; |
2198 | 0 | } |
2199 | 0 | pProperties[ nCurLen++ ] = std::move(aProp); |
2200 | 0 | } |
2201 | 0 | aProperties.realloc( nCurLen ); |
2202 | 0 | } |
2203 | 0 | else |
2204 | 0 | aProperties = xPropSetInfo->getProperties(); |
2205 | | |
2206 | | // build resulting sequence |
2207 | 0 | uno::Sequence< beans::PropertyValue > aOutSequence( aProperties.getLength() ); |
2208 | 0 | beans::PropertyValue* pOutSequence = aOutSequence.getArray(); |
2209 | 0 | sal_Int32 nOutLen = 0; |
2210 | 0 | for (const beans::Property& rProperty : aProperties) |
2211 | 0 | { |
2212 | | // calling 'regular' functions that will operate on the selection |
2213 | 0 | PropertyState eState = xPropSet->getPropertyState( rProperty.Name ); |
2214 | 0 | if (eState == PropertyState_DIRECT_VALUE) |
2215 | 0 | { |
2216 | 0 | pOutSequence->Name = rProperty.Name; |
2217 | 0 | pOutSequence->Handle = rProperty.Handle; |
2218 | 0 | pOutSequence->Value = xPropSet->getPropertyValue( rProperty.Name ); |
2219 | 0 | pOutSequence->State = eState; |
2220 | |
|
2221 | 0 | ++pOutSequence; |
2222 | 0 | ++nOutLen; |
2223 | 0 | } |
2224 | 0 | } |
2225 | 0 | aOutSequence.realloc( nOutLen ); |
2226 | |
|
2227 | 0 | return aOutSequence; |
2228 | 0 | } |
2229 | | |
2230 | | // XAccessibleHypertext |
2231 | | ::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkCount( ) |
2232 | 0 | { |
2233 | 0 | SvxAccessibleTextAdapter& rT = GetTextForwarder(); |
2234 | 0 | const sal_Int32 nPara = GetParagraphIndex(); |
2235 | |
|
2236 | 0 | std::vector<EFieldInfo> aFieldInfos = rT.GetFieldInfo( nPara ); |
2237 | 0 | sal_Int32 nHyperLinks = 0; |
2238 | 0 | sal_Int32 nFields = aFieldInfos.size(); |
2239 | 0 | for (sal_Int32 n = 0; n < nFields; ++n) |
2240 | 0 | { |
2241 | 0 | if ( dynamic_cast<const SvxURLField* >(aFieldInfos[n].pFieldItem->GetField() ) != nullptr) |
2242 | 0 | nHyperLinks++; |
2243 | 0 | } |
2244 | 0 | return nHyperLinks; |
2245 | 0 | } |
2246 | | |
2247 | | css::uno::Reference< css::accessibility::XAccessibleHyperlink > SAL_CALL AccessibleEditableTextPara::getHyperLink( ::sal_Int32 nLinkIndex ) |
2248 | 0 | { |
2249 | 0 | rtl::Reference< AccessibleHyperlink > xRef; |
2250 | |
|
2251 | 0 | SvxAccessibleTextAdapter& rT = GetTextForwarder(); |
2252 | 0 | const sal_Int32 nPara = GetParagraphIndex(); |
2253 | |
|
2254 | 0 | sal_Int32 nHyperLink = 0; |
2255 | 0 | for (const EFieldInfo& rField : rT.GetFieldInfo( nPara )) |
2256 | 0 | { |
2257 | 0 | if ( dynamic_cast<const SvxURLField* >(rField.pFieldItem->GetField()) != nullptr ) |
2258 | 0 | { |
2259 | 0 | if ( nHyperLink == nLinkIndex ) |
2260 | 0 | { |
2261 | 0 | sal_Int32 nEEStart = rField.aPosition.nIndex; |
2262 | | |
2263 | | // Translate EE Index to accessible index |
2264 | 0 | sal_Int32 nStart = rT.CalcEditEngineIndex( nPara, nEEStart ); |
2265 | 0 | sal_Int32 nEnd = nStart + rField.aCurrentText.getLength(); |
2266 | 0 | xRef = new AccessibleHyperlink( rT, new SvxFieldItem( *rField.pFieldItem ), nStart, nEnd, rField.aCurrentText ); |
2267 | 0 | break; |
2268 | 0 | } |
2269 | 0 | nHyperLink++; |
2270 | 0 | } |
2271 | 0 | } |
2272 | |
|
2273 | 0 | return xRef; |
2274 | 0 | } |
2275 | | |
2276 | | ::sal_Int32 SAL_CALL AccessibleEditableTextPara::getHyperLinkIndex( ::sal_Int32 nCharIndex ) |
2277 | 0 | { |
2278 | 0 | const sal_Int32 nPara = GetParagraphIndex(); |
2279 | 0 | SvxAccessibleTextAdapter& rT = GetTextForwarder(); |
2280 | |
|
2281 | 0 | const sal_Int32 nEEIndex = rT.CalcEditEngineIndex( nPara, nCharIndex ); |
2282 | 0 | sal_Int32 nHLIndex = -1; //i123620 |
2283 | 0 | sal_Int32 nHyperLink = 0; |
2284 | 0 | for (const EFieldInfo & rField : rT.GetFieldInfo( nPara )) |
2285 | 0 | { |
2286 | 0 | if ( dynamic_cast<const SvxURLField* >( rField.pFieldItem->GetField() ) != nullptr) |
2287 | 0 | { |
2288 | 0 | if ( rField.aPosition.nIndex == nEEIndex ) |
2289 | 0 | { |
2290 | 0 | nHLIndex = nHyperLink; |
2291 | 0 | break; |
2292 | 0 | } |
2293 | 0 | nHyperLink++; |
2294 | 0 | } |
2295 | 0 | } |
2296 | |
|
2297 | 0 | return nHLIndex; |
2298 | 0 | } |
2299 | | |
2300 | | // XAccessibleMultiLineText |
2301 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getLineNumberAtIndex( sal_Int32 nIndex ) |
2302 | 0 | { |
2303 | |
|
2304 | 0 | sal_Int32 nRes = -1; |
2305 | 0 | sal_Int32 nPara = GetParagraphIndex(); |
2306 | |
|
2307 | 0 | SvxTextForwarder &rCacheTF = GetTextForwarder(); |
2308 | 0 | const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); |
2309 | 0 | DBG_ASSERT( bValidPara, "getLineNumberAtIndex: current paragraph index out of range" ); |
2310 | 0 | if (bValidPara) |
2311 | 0 | { |
2312 | | // we explicitly allow for the index to point at the character right behind the text |
2313 | 0 | if (0 > nIndex || nIndex > rCacheTF.GetTextLen( nPara )) |
2314 | 0 | throw lang::IndexOutOfBoundsException(); |
2315 | 0 | nRes = rCacheTF.GetLineNumberAtIndex( nPara, nIndex ); |
2316 | 0 | } |
2317 | 0 | return nRes; |
2318 | 0 | } |
2319 | | |
2320 | | // XAccessibleMultiLineText |
2321 | | css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineNumber( sal_Int32 nLineNo ) |
2322 | 0 | { |
2323 | |
|
2324 | 0 | css::accessibility::TextSegment aResult; |
2325 | 0 | sal_Int32 nPara = GetParagraphIndex(); |
2326 | 0 | SvxTextForwarder &rCacheTF = GetTextForwarder(); |
2327 | 0 | const bool bValidPara = 0 <= nPara && nPara < rCacheTF.GetParagraphCount(); |
2328 | 0 | DBG_ASSERT( bValidPara, "getTextAtLineNumber: current paragraph index out of range" ); |
2329 | 0 | if (bValidPara) |
2330 | 0 | { |
2331 | 0 | if (0 > nLineNo || nLineNo >= rCacheTF.GetLineCount( nPara )) |
2332 | 0 | throw lang::IndexOutOfBoundsException(); |
2333 | 0 | sal_Int32 nStart = 0, nEnd = 0; |
2334 | 0 | rCacheTF.GetLineBoundaries( nStart, nEnd, nPara, nLineNo ); |
2335 | 0 | if (nStart >= 0 && nEnd >= 0) |
2336 | 0 | { |
2337 | 0 | try |
2338 | 0 | { |
2339 | 0 | aResult.SegmentText = getTextRange( nStart, nEnd ); |
2340 | 0 | aResult.SegmentStart = nStart; |
2341 | 0 | aResult.SegmentEnd = nEnd; |
2342 | 0 | } |
2343 | 0 | catch (const lang::IndexOutOfBoundsException&) |
2344 | 0 | { |
2345 | | // this is not the exception that should be raised in this function ... |
2346 | 0 | DBG_UNHANDLED_EXCEPTION("editeng"); |
2347 | 0 | } |
2348 | 0 | } |
2349 | 0 | } |
2350 | 0 | return aResult; |
2351 | 0 | } |
2352 | | |
2353 | | // XAccessibleMultiLineText |
2354 | | css::accessibility::TextSegment SAL_CALL AccessibleEditableTextPara::getTextAtLineWithCaret( ) |
2355 | 0 | { |
2356 | |
|
2357 | 0 | css::accessibility::TextSegment aResult; |
2358 | 0 | try |
2359 | 0 | { |
2360 | 0 | aResult = getTextAtLineNumber( getNumberOfLineWithCaret() ); |
2361 | 0 | } |
2362 | 0 | catch (const lang::IndexOutOfBoundsException&) |
2363 | 0 | { |
2364 | | // this one needs to be caught since this interface does not allow for it. |
2365 | 0 | } |
2366 | 0 | return aResult; |
2367 | 0 | } |
2368 | | |
2369 | | // XAccessibleMultiLineText |
2370 | | sal_Int32 SAL_CALL AccessibleEditableTextPara::getNumberOfLineWithCaret( ) |
2371 | 0 | { |
2372 | |
|
2373 | 0 | sal_Int32 nRes = -1; |
2374 | 0 | try |
2375 | 0 | { |
2376 | 0 | nRes = getLineNumberAtIndex( getCaretPosition() ); |
2377 | 0 | } |
2378 | 0 | catch (const lang::IndexOutOfBoundsException&) |
2379 | 0 | { |
2380 | | // this one needs to be caught since this interface does not allow for it. |
2381 | 0 | } |
2382 | 0 | return nRes; |
2383 | 0 | } |
2384 | | |
2385 | | } // end of namespace accessibility |
2386 | | |
2387 | | |
2388 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |