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