1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
28 #include <osl/diagnose.h>
29 #include <svl/itemset.hxx>
30 #include <tools/debug.hxx>
33 // Project-local header
36 #include <editeng/unoedprx.hxx>
37 #include <editeng/editdata.hxx>
38 #include <editeng/editeng.hxx>
39 #include <AccessibleStringWrap.hxx>
40 #include <editeng/outliner.hxx>
42 using namespace ::com::sun::star
;
46 class SvxAccessibleTextIndex
49 SvxAccessibleTextIndex() :
60 // Get/Set current paragraph
61 void SetParagraph( sal_Int32 nPara
)
65 sal_Int32
GetParagraph() const { return mnPara
; }
67 /** Set the index in the UAA semantic
70 The index from the UA API (fields and bullets are expanded)
73 The text forwarder to use in the calculations
75 void SetIndex( sal_Int32 nIndex
, const SvxTextForwarder
& rTF
);
76 void SetIndex( sal_Int32 nPara
, sal_Int32 nIndex
, const SvxTextForwarder
& rTF
) { SetParagraph(nPara
); SetIndex(nIndex
, rTF
); }
77 sal_Int32
GetIndex() const { return mnIndex
; }
79 /** Set the index in the edit engine semantic
81 Update the object state to reflect the given index position in
82 EditEngine/Outliner index values
85 The index from the edit engine (fields span exactly one index increment)
88 The text forwarder to use in the calculations
90 void SetEEIndex( sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
);
91 void SetEEIndex( sal_Int32 nPara
, sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
) { SetParagraph(nPara
); SetEEIndex(nEEIndex
, rTF
); }
92 sal_Int32
GetEEIndex() const;
94 void SetFieldOffset( sal_Int32 nOffset
, sal_Int32 nLen
) { mnFieldOffset
= nOffset
; mnFieldLen
= nLen
; }
95 sal_Int32
GetFieldOffset() const { return mnFieldOffset
; }
96 sal_Int32
GetFieldLen() const { return mnFieldLen
; }
97 void AreInField() { mbInField
= true; }
98 bool InField() const { return mbInField
; }
100 void SetBulletOffset( sal_Int32 nOffset
, sal_Int32 nLen
) { mnBulletOffset
= nOffset
; mnBulletLen
= nLen
; }
101 sal_Int32
GetBulletOffset() const { return mnBulletOffset
; }
102 sal_Int32
GetBulletLen() const { return mnBulletLen
; }
103 bool InBullet() const { return mbInBullet
; }
105 /// returns false if the given range is non-editable (e.g. contains bullets or _parts_ of fields)
106 bool IsEditableRange( const SvxAccessibleTextIndex
& rEnd
) const;
112 sal_Int32 mnFieldOffset
;
113 sal_Int32 mnFieldLen
;
115 sal_Int32 mnBulletOffset
;
116 sal_Int32 mnBulletLen
;
122 static ESelection
MakeEESelection( const SvxAccessibleTextIndex
& rStart
, const SvxAccessibleTextIndex
& rEnd
)
124 // deal with field special case: to really get a field contained
125 // within a selection, the start index must be before or on the
126 // field, the end index after it.
128 // The SvxAccessibleTextIndex.GetEEIndex method gives the index on
129 // the field, as long the input index is on the field. Thus,
130 // correction necessary for the end index
132 // Therefore, for _ranges_, if part of the field is touched, all
133 // of the field must be selected
134 if( rStart
.GetParagraph() <= rEnd
.GetParagraph() ||
135 (rStart
.GetParagraph() == rEnd
.GetParagraph() &&
136 rStart
.GetEEIndex() <= rEnd
.GetEEIndex()) )
138 if( rEnd
.InField() && rEnd
.GetFieldOffset() )
139 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex(),
140 rEnd
.GetParagraph(), rEnd
.GetEEIndex()+1 );
142 else if( rStart
.GetParagraph() > rEnd
.GetParagraph() ||
143 (rStart
.GetParagraph() == rEnd
.GetParagraph() &&
144 rStart
.GetEEIndex() > rEnd
.GetEEIndex()) )
146 if( rStart
.InField() && rStart
.GetFieldOffset() )
147 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex()+1,
148 rEnd
.GetParagraph(), rEnd
.GetEEIndex() );
151 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex(),
152 rEnd
.GetParagraph(), rEnd
.GetEEIndex() );
155 static ESelection
MakeEESelection( const SvxAccessibleTextIndex
& rIndex
)
157 return ESelection( rIndex
.GetParagraph(), rIndex
.GetEEIndex(),
158 rIndex
.GetParagraph(), rIndex
.GetEEIndex() + 1 );
161 sal_Int32
SvxAccessibleTextIndex::GetEEIndex() const
163 DBG_ASSERT(mnEEIndex
>= 0,
164 "SvxAccessibleTextIndex::GetEEIndex: index value overflow");
169 void SvxAccessibleTextIndex::SetEEIndex( sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
)
180 mnEEIndex
= nEEIndex
;
182 // calculate unknowns
183 sal_Int32 nCurrField
, nFieldCount
= rTF
.GetFieldCount( GetParagraph() );
187 EBulletInfo aBulletInfo
= rTF
.GetBulletInfo( GetParagraph() );
190 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
191 aBulletInfo
.bVisible
&&
192 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
194 mnIndex
+= aBulletInfo
.aText
.getLength();
197 for( nCurrField
=0; nCurrField
< nFieldCount
; ++nCurrField
)
199 EFieldInfo
aFieldInfo( rTF
.GetFieldInfo( GetParagraph(), nCurrField
) );
201 if( aFieldInfo
.aPosition
.nIndex
> nEEIndex
)
204 if( aFieldInfo
.aPosition
.nIndex
== nEEIndex
)
210 mnIndex
+= std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0));
214 void SvxAccessibleTextIndex::SetIndex( sal_Int32 nIndex
, const SvxTextForwarder
& rTF
)
227 // calculate unknowns
228 sal_Int32 nCurrField
, nFieldCount
= rTF
.GetFieldCount( GetParagraph() );
230 DBG_ASSERT(nIndex
>= 0,
231 "SvxAccessibleTextIndex::SetIndex: index value overflow");
235 EBulletInfo aBulletInfo
= rTF
.GetBulletInfo( GetParagraph() );
238 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
239 aBulletInfo
.bVisible
&&
240 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
242 sal_Int32 nBulletLen
= aBulletInfo
.aText
.getLength();
244 if( nIndex
< nBulletLen
)
247 SetBulletOffset( nIndex
, nBulletLen
);
252 mnEEIndex
= mnEEIndex
- nBulletLen
;
255 for( nCurrField
=0; nCurrField
< nFieldCount
; ++nCurrField
)
257 EFieldInfo
aFieldInfo( rTF
.GetFieldInfo( GetParagraph(), nCurrField
) );
259 // we're before a field
260 if( aFieldInfo
.aPosition
.nIndex
> mnEEIndex
)
263 mnEEIndex
-= std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0));
265 // we're within a field
266 if( aFieldInfo
.aPosition
.nIndex
>= mnEEIndex
)
269 SetFieldOffset( std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0)) - (aFieldInfo
.aPosition
.nIndex
- mnEEIndex
),
270 aFieldInfo
.aCurrentText
.getLength() );
271 mnEEIndex
= aFieldInfo
.aPosition
.nIndex
;
277 bool SvxAccessibleTextIndex::IsEditableRange( const SvxAccessibleTextIndex
& rEnd
) const
279 if( GetIndex() > rEnd
.GetIndex() )
280 return rEnd
.IsEditableRange( *this );
282 if( InBullet() || rEnd
.InBullet() )
285 if( InField() && GetFieldOffset() )
286 return false; // within field
288 if( rEnd
.InField() && rEnd
.GetFieldOffset() >= rEnd
.GetFieldLen() - 1 )
289 return false; // within field
295 SvxEditSourceAdapter::SvxEditSourceAdapter() : mbEditSourceValid( false )
299 SvxEditSourceAdapter::~SvxEditSourceAdapter()
303 std::unique_ptr
<SvxEditSource
> SvxEditSourceAdapter::Clone() const
305 if( mbEditSourceValid
&& mpAdaptee
)
307 std::unique_ptr
< SvxEditSource
> pClonedAdaptee( mpAdaptee
->Clone() );
311 std::unique_ptr
<SvxEditSourceAdapter
> pClone(new SvxEditSourceAdapter());
312 pClone
->SetEditSource( std::move(pClonedAdaptee
) );
313 return std::unique_ptr
< SvxEditSource
>(pClone
.release());
320 SvxAccessibleTextAdapter
* SvxEditSourceAdapter::GetTextForwarderAdapter()
322 if( mbEditSourceValid
&& mpAdaptee
)
324 SvxTextForwarder
* pTextForwarder
= mpAdaptee
->GetTextForwarder();
328 maTextAdapter
.SetForwarder(*pTextForwarder
);
330 return &maTextAdapter
;
337 SvxTextForwarder
* SvxEditSourceAdapter::GetTextForwarder()
339 return GetTextForwarderAdapter();
342 SvxViewForwarder
* SvxEditSourceAdapter::GetViewForwarder()
344 if( mbEditSourceValid
&& mpAdaptee
)
345 return mpAdaptee
->GetViewForwarder();
350 SvxAccessibleTextEditViewAdapter
* SvxEditSourceAdapter::GetEditViewForwarderAdapter( bool bCreate
)
352 if( mbEditSourceValid
&& mpAdaptee
)
354 SvxEditViewForwarder
* pEditViewForwarder
= mpAdaptee
->GetEditViewForwarder(bCreate
);
356 if( pEditViewForwarder
)
358 SvxAccessibleTextAdapter
* pTextAdapter
= GetTextForwarderAdapter();
362 maEditViewAdapter
.SetForwarder(*pEditViewForwarder
, *pTextAdapter
);
364 return &maEditViewAdapter
;
372 SvxEditViewForwarder
* SvxEditSourceAdapter::GetEditViewForwarder( bool bCreate
)
374 return GetEditViewForwarderAdapter( bCreate
);
377 void SvxEditSourceAdapter::UpdateData()
379 if( mbEditSourceValid
&& mpAdaptee
)
380 mpAdaptee
->UpdateData();
383 SfxBroadcaster
& SvxEditSourceAdapter::GetBroadcaster() const
385 if( mbEditSourceValid
&& mpAdaptee
)
386 return mpAdaptee
->GetBroadcaster();
388 return maDummyBroadcaster
;
391 void SvxEditSourceAdapter::SetEditSource( std::unique_ptr
< SvxEditSource
> && pAdaptee
)
395 mpAdaptee
= std::move(pAdaptee
);
396 mbEditSourceValid
= true;
400 // do a lazy delete (prevents us from deleting the broadcaster
401 // from within a broadcast in
402 // AccessibleTextHelper_Impl::Notify)
403 mbEditSourceValid
= false;
407 SvxAccessibleTextAdapter::SvxAccessibleTextAdapter()
408 : mpTextForwarder(nullptr)
412 SvxAccessibleTextAdapter::~SvxAccessibleTextAdapter()
416 sal_Int32
SvxAccessibleTextAdapter::GetParagraphCount() const
418 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
420 return mpTextForwarder
->GetParagraphCount();
423 sal_Int32
SvxAccessibleTextAdapter::GetTextLen( sal_Int32 nParagraph
) const
425 SvxAccessibleTextIndex aIndex
;
426 aIndex
.SetEEIndex( nParagraph
, mpTextForwarder
->GetTextLen( nParagraph
), *this );
428 return aIndex
.GetIndex();
431 OUString
SvxAccessibleTextAdapter::GetText( const ESelection
& rSel
) const
433 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
435 SvxAccessibleTextIndex aStartIndex
;
436 SvxAccessibleTextIndex aEndIndex
;
438 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
439 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
441 // normalize selection
442 if( rSel
.nStartPara
> rSel
.nEndPara
||
443 (rSel
.nStartPara
== rSel
.nEndPara
&& rSel
.nStartPos
> rSel
.nEndPos
) )
445 std::swap( aStartIndex
, aEndIndex
);
448 OUString sStr
= mpTextForwarder
->GetText( MakeEESelection(aStartIndex
, aEndIndex
) );
450 // trim field text, if necessary
451 if( aStartIndex
.InField() )
453 DBG_ASSERT(aStartIndex
.GetFieldOffset() >= 0,
454 "SvxAccessibleTextIndex::GetText: index value overflow");
456 sStr
= sStr
.copy( aStartIndex
.GetFieldOffset() );
458 if( aEndIndex
.InField() && aEndIndex
.GetFieldOffset() )
460 DBG_ASSERT(sStr
.getLength() - (aEndIndex
.GetFieldLen() - aEndIndex
.GetFieldOffset()) >= 0,
461 "SvxAccessibleTextIndex::GetText: index value overflow");
463 sStr
= sStr
.copy(0, sStr
.getLength() - (aEndIndex
.GetFieldLen() - aEndIndex
.GetFieldOffset()) );
466 EBulletInfo aBulletInfo2
= GetBulletInfo( aEndIndex
.GetParagraph() );
468 if( aEndIndex
.InBullet() )
470 // append trailing bullet
471 sStr
+= aBulletInfo2
.aText
;
473 DBG_ASSERT(sStr
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) >= 0,
474 "SvxAccessibleTextIndex::GetText: index value overflow");
476 sStr
= sStr
.copy(0, sStr
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) );
478 else if( aStartIndex
.GetParagraph() != aEndIndex
.GetParagraph() &&
479 HaveTextBullet( aEndIndex
.GetParagraph() ) )
481 OUString sBullet
= aBulletInfo2
.aText
;
483 DBG_ASSERT(sBullet
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) >= 0,
484 "SvxAccessibleTextIndex::GetText: index value overflow");
486 sBullet
= sBullet
.copy(0, sBullet
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) );
489 sStr
= sStr
.replaceAt( GetTextLen(aStartIndex
.GetParagraph()) - aStartIndex
.GetIndex(), 0, sBullet
);
495 SfxItemSet
SvxAccessibleTextAdapter::GetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
) const
497 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
499 SvxAccessibleTextIndex aStartIndex
;
500 SvxAccessibleTextIndex aEndIndex
;
502 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
503 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
505 return mpTextForwarder
->GetAttribs( MakeEESelection(aStartIndex
, aEndIndex
), nOnlyHardAttrib
);
508 SfxItemSet
SvxAccessibleTextAdapter::GetParaAttribs( sal_Int32 nPara
) const
510 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
512 return mpTextForwarder
->GetParaAttribs( nPara
);
515 void SvxAccessibleTextAdapter::SetParaAttribs( sal_Int32 nPara
, const SfxItemSet
& rSet
)
517 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
519 mpTextForwarder
->SetParaAttribs( nPara
, rSet
);
522 void SvxAccessibleTextAdapter::RemoveAttribs( const ESelection
& )
526 void SvxAccessibleTextAdapter::GetPortions( sal_Int32 nPara
, std::vector
<sal_Int32
>& rList
) const
528 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
530 mpTextForwarder
->GetPortions( nPara
, rList
);
533 SfxItemState
SvxAccessibleTextAdapter::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
535 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
537 SvxAccessibleTextIndex aStartIndex
;
538 SvxAccessibleTextIndex aEndIndex
;
540 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
541 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
543 return mpTextForwarder
->GetItemState( MakeEESelection(aStartIndex
, aEndIndex
),
547 SfxItemState
SvxAccessibleTextAdapter::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
549 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
551 return mpTextForwarder
->GetItemState( nPara
, nWhich
);
554 void SvxAccessibleTextAdapter::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
556 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
558 SvxAccessibleTextIndex aStartIndex
;
559 SvxAccessibleTextIndex aEndIndex
;
561 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
562 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
564 mpTextForwarder
->QuickInsertText( rText
,
565 MakeEESelection(aStartIndex
, aEndIndex
) );
568 void SvxAccessibleTextAdapter::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
570 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
572 SvxAccessibleTextIndex aStartIndex
;
573 SvxAccessibleTextIndex aEndIndex
;
575 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
576 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
578 mpTextForwarder
->QuickInsertField( rFld
,
579 MakeEESelection(aStartIndex
, aEndIndex
) );
582 void SvxAccessibleTextAdapter::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
584 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
586 SvxAccessibleTextIndex aStartIndex
;
587 SvxAccessibleTextIndex aEndIndex
;
589 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
590 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
592 mpTextForwarder
->QuickSetAttribs( rSet
,
593 MakeEESelection(aStartIndex
, aEndIndex
) );
596 void SvxAccessibleTextAdapter::QuickInsertLineBreak( const ESelection
& rSel
)
598 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
600 SvxAccessibleTextIndex aStartIndex
;
601 SvxAccessibleTextIndex aEndIndex
;
603 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
604 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
606 mpTextForwarder
->QuickInsertLineBreak( MakeEESelection(aStartIndex
, aEndIndex
) );
609 SfxItemPool
* SvxAccessibleTextAdapter::GetPool() const
611 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
613 return mpTextForwarder
->GetPool();
616 OUString
SvxAccessibleTextAdapter::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, std::optional
<Color
>& rpTxtColor
, std::optional
<Color
>& rpFldColor
)
618 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
620 return mpTextForwarder
->CalcFieldValue( rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
);
623 void SvxAccessibleTextAdapter::FieldClicked( const SvxFieldItem
& rField
)
625 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
627 mpTextForwarder
->FieldClicked( rField
);
630 sal_Int32
SvxAccessibleTextAdapter::CalcEditEngineIndex( sal_Int32 nPara
, sal_Int32 nLogicalIndex
)
632 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
634 SvxAccessibleTextIndex aIndex
;
635 aIndex
.SetIndex(nPara
, nLogicalIndex
, *mpTextForwarder
);
636 return aIndex
.GetEEIndex();
639 bool SvxAccessibleTextAdapter::IsValid() const
641 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
643 if( mpTextForwarder
)
644 return mpTextForwarder
->IsValid();
649 LanguageType
SvxAccessibleTextAdapter::GetLanguage( sal_Int32 nPara
, sal_Int32 nPos
) const
651 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
653 SvxAccessibleTextIndex aIndex
;
655 aIndex
.SetIndex( nPara
, nPos
, *this );
657 return mpTextForwarder
->GetLanguage( nPara
, aIndex
.GetEEIndex() );
660 sal_Int32
SvxAccessibleTextAdapter::GetFieldCount( sal_Int32 nPara
) const
662 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
664 return mpTextForwarder
->GetFieldCount( nPara
);
667 EFieldInfo
SvxAccessibleTextAdapter::GetFieldInfo( sal_Int32 nPara
, sal_uInt16 nField
) const
669 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
671 return mpTextForwarder
->GetFieldInfo( nPara
, nField
);
674 EBulletInfo
SvxAccessibleTextAdapter::GetBulletInfo( sal_Int32 nPara
) const
676 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
678 return mpTextForwarder
->GetBulletInfo( nPara
);
681 tools::Rectangle
SvxAccessibleTextAdapter::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
683 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
685 SvxAccessibleTextIndex aIndex
;
686 aIndex
.SetIndex( nPara
, nIndex
, *this );
688 // preset if anything goes wrong below
689 // n-th char in GetParagraphIndex's paragraph
690 tools::Rectangle aRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
692 if( aIndex
.InBullet() )
694 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
696 OutputDevice
* pOutDev
= GetRefDevice();
698 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
700 // preset if anything goes wrong below
701 aRect
= aBulletInfo
.aBounds
; // better than nothing
704 AccessibleStringWrap
aStringWrap( *pOutDev
, aBulletInfo
.aFont
, aBulletInfo
.aText
);
706 aStringWrap
.GetCharacterBounds( aIndex
.GetBulletOffset(), aRect
);
707 aRect
.Move( aBulletInfo
.aBounds
.Left(), aBulletInfo
.aBounds
.Top() );
712 // handle field content manually
713 if( aIndex
.InField() )
715 OutputDevice
* pOutDev
= GetRefDevice();
717 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
721 ESelection aSel
= MakeEESelection( aIndex
);
723 SvxFont aFont
= EditEngine::CreateSvxFontFromItemSet( mpTextForwarder
->GetAttribs( aSel
) );
724 AccessibleStringWrap
aStringWrap( *pOutDev
,
726 mpTextForwarder
->GetText( aSel
) );
728 tools::Rectangle aStartRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
730 aStringWrap
.GetCharacterBounds( aIndex
.GetFieldOffset(), aRect
);
731 aRect
.Move( aStartRect
.Left(), aStartRect
.Top() );
739 tools::Rectangle
SvxAccessibleTextAdapter::GetParaBounds( sal_Int32 nPara
) const
741 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
743 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
745 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
746 aBulletInfo
.bVisible
&&
747 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
749 // include bullet in para bounding box
750 tools::Rectangle
aRect( mpTextForwarder
->GetParaBounds( nPara
) );
752 aRect
.Union( aBulletInfo
.aBounds
);
757 return mpTextForwarder
->GetParaBounds( nPara
);
760 MapMode
SvxAccessibleTextAdapter::GetMapMode() const
762 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
764 return mpTextForwarder
->GetMapMode();
767 OutputDevice
* SvxAccessibleTextAdapter::GetRefDevice() const
769 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
771 return mpTextForwarder
->GetRefDevice();
774 bool SvxAccessibleTextAdapter::GetIndexAtPoint( const Point
& rPoint
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
776 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
778 if( !mpTextForwarder
->GetIndexAtPoint( rPoint
, nPara
, nIndex
) )
781 SvxAccessibleTextIndex aIndex
;
782 aIndex
.SetEEIndex(nPara
, nIndex
, *this);
784 DBG_ASSERT(aIndex
.GetIndex() >= 0,
785 "SvxAccessibleTextIndex::SetIndex: index value overflow");
787 nIndex
= aIndex
.GetIndex();
789 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
792 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
793 aBulletInfo
.bVisible
&&
794 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
796 if( aBulletInfo
.aBounds
.IsInside( rPoint
) )
798 OutputDevice
* pOutDev
= GetRefDevice();
800 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
805 AccessibleStringWrap
aStringWrap( *pOutDev
, aBulletInfo
.aFont
, aBulletInfo
.aText
);
807 Point aPoint
= rPoint
;
808 aPoint
.Move( -aBulletInfo
.aBounds
.Left(), -aBulletInfo
.aBounds
.Top() );
810 DBG_ASSERT(aStringWrap
.GetIndexAtPoint( aPoint
) >= 0,
811 "SvxAccessibleTextIndex::SetIndex: index value overflow");
813 nIndex
= aStringWrap
.GetIndexAtPoint( aPoint
);
818 if( aIndex
.InField() )
820 OutputDevice
* pOutDev
= GetRefDevice();
822 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
827 ESelection aSelection
= MakeEESelection( aIndex
);
828 SvxFont aFont
= EditEngine::CreateSvxFontFromItemSet( mpTextForwarder
->GetAttribs( aSelection
) );
829 AccessibleStringWrap
aStringWrap( *pOutDev
,
831 mpTextForwarder
->GetText( aSelection
) );
833 tools::Rectangle aRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
834 Point aPoint
= rPoint
;
835 aPoint
.Move( -aRect
.Left(), -aRect
.Top() );
837 DBG_ASSERT(aIndex
.GetIndex() + aStringWrap
.GetIndexAtPoint( rPoint
) >= 0,
838 "SvxAccessibleTextIndex::SetIndex: index value overflow");
840 nIndex
= (aIndex
.GetIndex() + aStringWrap
.GetIndexAtPoint( aPoint
));
847 bool SvxAccessibleTextAdapter::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
849 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
851 SvxAccessibleTextIndex aIndex
;
852 aIndex
.SetIndex(nPara
, nIndex
, *this);
853 nIndex
= aIndex
.GetEEIndex();
855 if( aIndex
.InBullet() )
857 DBG_ASSERT(aIndex
.GetBulletLen() >= 0,
858 "SvxAccessibleTextIndex::SetIndex: index value overflow");
860 // always treat bullet as separate word
862 nEnd
= aIndex
.GetBulletLen();
867 if( aIndex
.InField() )
869 DBG_ASSERT(aIndex
.GetIndex() - aIndex
.GetFieldOffset() >= 0 &&
870 nStart
+ aIndex
.GetFieldLen() >= 0,
871 "SvxAccessibleTextIndex::SetIndex: index value overflow");
873 // always treat field as separate word
874 // TODO: to circumvent this, _we_ would have to do the break iterator stuff!
875 nStart
= aIndex
.GetIndex() - aIndex
.GetFieldOffset();
876 nEnd
= nStart
+ aIndex
.GetFieldLen();
881 if( !mpTextForwarder
->GetWordIndices( nPara
, nIndex
, nStart
, nEnd
) )
884 aIndex
.SetEEIndex( nPara
, nStart
, *this );
885 DBG_ASSERT(aIndex
.GetIndex() >= 0,
886 "SvxAccessibleTextIndex::SetIndex: index value overflow");
887 nStart
= aIndex
.GetIndex();
889 aIndex
.SetEEIndex( nPara
, nEnd
, *this );
890 DBG_ASSERT(aIndex
.GetIndex() >= 0,
891 "SvxAccessibleTextIndex::SetIndex: index value overflow");
892 nEnd
= aIndex
.GetIndex();
897 bool SvxAccessibleTextAdapter::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool /* bInCell */ ) const
899 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
901 SvxAccessibleTextIndex aIndex
;
902 aIndex
.SetIndex(nPara
, nIndex
, *this);
903 nIndex
= aIndex
.GetEEIndex();
905 if( aIndex
.InBullet() )
907 DBG_ASSERT(aIndex
.GetBulletLen() >= 0,
908 "SvxAccessibleTextIndex::SetIndex: index value overflow");
910 // always treat bullet as distinct attribute
912 nEndIndex
= aIndex
.GetBulletLen();
917 if( aIndex
.InField() )
919 DBG_ASSERT(aIndex
.GetIndex() - aIndex
.GetFieldOffset() >= 0,
920 "SvxAccessibleTextIndex::SetIndex: index value overflow");
922 // always treat field as distinct attribute
923 nStartIndex
= aIndex
.GetIndex() - aIndex
.GetFieldOffset();
924 nEndIndex
= nStartIndex
+ aIndex
.GetFieldLen();
929 if( !mpTextForwarder
->GetAttributeRun( nStartIndex
, nEndIndex
, nPara
, nIndex
) )
932 aIndex
.SetEEIndex( nPara
, nStartIndex
, *this );
933 DBG_ASSERT(aIndex
.GetIndex() >= 0,
934 "SvxAccessibleTextIndex::SetIndex: index value overflow");
935 nStartIndex
= aIndex
.GetIndex();
937 aIndex
.SetEEIndex( nPara
, nEndIndex
, *this );
938 DBG_ASSERT(aIndex
.GetIndex() >= 0,
939 "SvxAccessibleTextIndex::SetIndex: index value overflow");
940 nEndIndex
= aIndex
.GetIndex();
945 sal_Int32
SvxAccessibleTextAdapter::GetLineCount( sal_Int32 nPara
) const
947 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
949 return mpTextForwarder
->GetLineCount( nPara
);
952 sal_Int32
SvxAccessibleTextAdapter::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
954 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
956 SvxAccessibleTextIndex aEndIndex
;
958 sal_Int32 nCurrIndex
, nLastIndex
;
959 for( nCurrLine
=0, nCurrIndex
=0, nLastIndex
=0; nCurrLine
<=nLine
; ++nCurrLine
)
961 nLastIndex
= nCurrIndex
;
963 nCurrIndex
+ mpTextForwarder
->GetLineLen( nPara
, nCurrLine
);
966 aEndIndex
.SetEEIndex( nPara
, nCurrIndex
, *this );
969 SvxAccessibleTextIndex aStartIndex
;
970 aStartIndex
.SetEEIndex( nPara
, nLastIndex
, *this );
972 return aEndIndex
.GetIndex() - aStartIndex
.GetIndex();
975 return aEndIndex
.GetIndex();
978 void SvxAccessibleTextAdapter::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nParagraph
, sal_Int32 nLine
) const
980 mpTextForwarder
->GetLineBoundaries( rStart
, rEnd
, nParagraph
, nLine
);
983 sal_Int32
SvxAccessibleTextAdapter::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
985 return mpTextForwarder
->GetLineNumberAtIndex( nPara
, nIndex
);
988 bool SvxAccessibleTextAdapter::Delete( const ESelection
& rSel
)
990 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
992 SvxAccessibleTextIndex aStartIndex
;
993 SvxAccessibleTextIndex aEndIndex
;
995 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
996 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
998 return mpTextForwarder
->Delete( MakeEESelection(aStartIndex
, aEndIndex
) );
1001 bool SvxAccessibleTextAdapter::InsertText( const OUString
& rStr
, const ESelection
& rSel
)
1003 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1005 SvxAccessibleTextIndex aStartIndex
;
1006 SvxAccessibleTextIndex aEndIndex
;
1008 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
1009 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
1011 return mpTextForwarder
->InsertText( rStr
, MakeEESelection(aStartIndex
, aEndIndex
) );
1014 bool SvxAccessibleTextAdapter::QuickFormatDoc( bool bFull
)
1016 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1018 return mpTextForwarder
->QuickFormatDoc( bFull
);
1021 sal_Int16
SvxAccessibleTextAdapter::GetDepth( sal_Int32 nPara
) const
1023 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1025 return mpTextForwarder
->GetDepth( nPara
);
1028 bool SvxAccessibleTextAdapter::SetDepth( sal_Int32 nPara
, sal_Int16 nNewDepth
)
1030 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1032 return mpTextForwarder
->SetDepth( nPara
, nNewDepth
);
1035 void SvxAccessibleTextAdapter::SetForwarder( SvxTextForwarder
& rForwarder
)
1037 mpTextForwarder
= &rForwarder
;
1040 bool SvxAccessibleTextAdapter::HaveImageBullet( sal_Int32 nPara
) const
1042 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
1044 return ( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
1045 aBulletInfo
.bVisible
&&
1046 aBulletInfo
.nType
== SVX_NUM_BITMAP
);
1049 bool SvxAccessibleTextAdapter::HaveTextBullet( sal_Int32 nPara
) const
1051 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
1053 return ( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
1054 aBulletInfo
.bVisible
&&
1055 aBulletInfo
.nType
!= SVX_NUM_BITMAP
);
1058 bool SvxAccessibleTextAdapter::IsEditable( const ESelection
& rSel
)
1060 SvxAccessibleTextIndex aStartIndex
;
1061 SvxAccessibleTextIndex aEndIndex
;
1063 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
1064 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
1066 // normalize selection
1067 if( rSel
.nStartPara
> rSel
.nEndPara
||
1068 (rSel
.nStartPara
== rSel
.nEndPara
&& rSel
.nStartPos
> rSel
.nEndPos
) )
1070 std::swap( aStartIndex
, aEndIndex
);
1073 return aStartIndex
.IsEditableRange( aEndIndex
);
1076 const SfxItemSet
* SvxAccessibleTextAdapter::GetEmptyItemSetPtr()
1078 OSL_FAIL( "not implemented" );
1082 void SvxAccessibleTextAdapter::AppendParagraph()
1084 OSL_FAIL( "not implemented" );
1087 sal_Int32
SvxAccessibleTextAdapter::AppendTextPortion( sal_Int32
, const OUString
&, const SfxItemSet
& )
1089 OSL_FAIL( "not implemented" );
1092 void SvxAccessibleTextAdapter::CopyText(const SvxTextForwarder
&)
1094 OSL_FAIL( "not implemented" );
1097 SvxAccessibleTextEditViewAdapter::SvxAccessibleTextEditViewAdapter()
1098 : mpViewForwarder(nullptr)
1099 , mpTextForwarder(nullptr)
1103 SvxAccessibleTextEditViewAdapter::~SvxAccessibleTextEditViewAdapter()
1107 bool SvxAccessibleTextEditViewAdapter::IsValid() const
1109 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1111 if( mpViewForwarder
)
1112 return mpViewForwarder
->IsValid();
1117 Point
SvxAccessibleTextEditViewAdapter::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
) const
1119 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1121 return mpViewForwarder
->LogicToPixel(rPoint
, rMapMode
);
1124 Point
SvxAccessibleTextEditViewAdapter::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
) const
1126 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1128 return mpViewForwarder
->PixelToLogic(rPoint
, rMapMode
);
1131 bool SvxAccessibleTextEditViewAdapter::GetSelection( ESelection
& rSel
) const
1133 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1135 ESelection aSelection
;
1137 if( !mpViewForwarder
->GetSelection( aSelection
) )
1140 SvxAccessibleTextIndex aStartIndex
;
1141 SvxAccessibleTextIndex aEndIndex
;
1143 aStartIndex
.SetEEIndex( aSelection
.nStartPara
, aSelection
.nStartPos
, *mpTextForwarder
);
1144 aEndIndex
.SetEEIndex( aSelection
.nEndPara
, aSelection
.nEndPos
, *mpTextForwarder
);
1146 DBG_ASSERT(aStartIndex
.GetIndex() >= 0 &&
1147 aEndIndex
.GetIndex() >= 0,
1148 "SvxAccessibleTextEditViewAdapter::GetSelection: index value overflow");
1150 rSel
= ESelection( aStartIndex
.GetParagraph(), aStartIndex
.GetIndex(),
1151 aEndIndex
.GetParagraph(), aEndIndex
.GetIndex() );
1156 bool SvxAccessibleTextEditViewAdapter::SetSelection( const ESelection
& rSel
)
1158 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1160 SvxAccessibleTextIndex aStartIndex
;
1161 SvxAccessibleTextIndex aEndIndex
;
1163 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *mpTextForwarder
);
1164 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *mpTextForwarder
);
1166 return mpViewForwarder
->SetSelection( MakeEESelection(aStartIndex
, aEndIndex
) );
1169 bool SvxAccessibleTextEditViewAdapter::Copy()
1171 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1173 return mpViewForwarder
->Copy();
1176 bool SvxAccessibleTextEditViewAdapter::Cut()
1178 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1180 return mpViewForwarder
->Cut();
1183 bool SvxAccessibleTextEditViewAdapter::Paste()
1185 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1187 return mpViewForwarder
->Paste();
1190 void SvxAccessibleTextEditViewAdapter::SetForwarder( SvxEditViewForwarder
& rForwarder
,
1191 SvxAccessibleTextAdapter
& rTextForwarder
)
1193 mpViewForwarder
= &rForwarder
;
1194 mpTextForwarder
= &rTextForwarder
;
1197 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */