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 .
29 #include <vcl/window.hxx>
30 #include <vcl/svapp.hxx>
31 #include <tools/debug.hxx>
34 // Project-local header
37 #include <editeng/unoedprx.hxx>
38 #include <editeng/unotext.hxx>
39 #include <editeng/unoedhlp.hxx>
40 #include <editeng/editdata.hxx>
41 #include <editeng/editeng.hxx>
42 #include <editeng/editview.hxx>
43 #include <editeng/AccessibleStringWrap.hxx>
44 #include <editeng/outliner.hxx>
46 using namespace ::com::sun::star
;
49 class SvxAccessibleTextIndex
52 SvxAccessibleTextIndex() :
63 // Get/Set current paragraph
64 void SetParagraph( sal_Int32 nPara
)
68 sal_Int32
GetParagraph() const { return mnPara
; }
70 /** Set the index in the UAA semantic
73 The index from the UA API (fields and bullets are expanded)
76 The text forwarder to use in the calculations
78 void SetIndex( sal_Int32 nIndex
, const SvxTextForwarder
& rTF
);
79 void SetIndex( sal_Int32 nPara
, sal_Int32 nIndex
, const SvxTextForwarder
& rTF
) { SetParagraph(nPara
); SetIndex(nIndex
, rTF
); }
80 sal_Int32
GetIndex() const { return mnIndex
; }
82 /** Set the index in the edit engine semantic
84 Update the object state to reflect the given index position in
85 EditEngine/Outliner index values
88 The index from the edit engine (fields span exactly one index increment)
91 The text forwarder to use in the calculations
93 void SetEEIndex( sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
);
94 void SetEEIndex( sal_Int32 nPara
, sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
) { SetParagraph(nPara
); SetEEIndex(nEEIndex
, rTF
); }
95 sal_Int32
GetEEIndex() const;
97 void SetFieldOffset( sal_Int32 nOffset
, sal_Int32 nLen
) { mnFieldOffset
= nOffset
; mnFieldLen
= nLen
; }
98 sal_Int32
GetFieldOffset() const { return mnFieldOffset
; }
99 sal_Int32
GetFieldLen() const { return mnFieldLen
; }
100 void AreInField() { mbInField
= true; }
101 bool InField() const { return mbInField
; }
103 void SetBulletOffset( sal_Int32 nOffset
, sal_Int32 nLen
) { mnBulletOffset
= nOffset
; mnBulletLen
= nLen
; }
104 sal_Int32
GetBulletOffset() const { return mnBulletOffset
; }
105 sal_Int32
GetBulletLen() const { return mnBulletLen
; }
106 bool InBullet() const { return mbInBullet
; }
108 /// returns false if the given range is non-editable (e.g. contains bullets or _parts_ of fields)
109 bool IsEditableRange( const SvxAccessibleTextIndex
& rEnd
) const;
115 sal_Int32 mnFieldOffset
;
116 sal_Int32 mnFieldLen
;
118 sal_Int32 mnBulletOffset
;
119 sal_Int32 mnBulletLen
;
123 static ESelection
MakeEESelection( const SvxAccessibleTextIndex
& rStart
, const SvxAccessibleTextIndex
& rEnd
)
125 // deal with field special case: to really get a field contained
126 // within a selection, the start index must be before or on the
127 // field, the end index after it.
129 // The SvxAccessibleTextIndex.GetEEIndex method gives the index on
130 // the field, as long the input index is on the field. Thus,
131 // correction necessary for the end index
133 // Therefore, for _ranges_, if part of the field is touched, all
134 // of the field must be selected
135 if( rStart
.GetParagraph() <= rEnd
.GetParagraph() ||
136 (rStart
.GetParagraph() == rEnd
.GetParagraph() &&
137 rStart
.GetEEIndex() <= rEnd
.GetEEIndex()) )
139 if( rEnd
.InField() && rEnd
.GetFieldOffset() )
140 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex(),
141 rEnd
.GetParagraph(), rEnd
.GetEEIndex()+1 );
143 else if( rStart
.GetParagraph() > rEnd
.GetParagraph() ||
144 (rStart
.GetParagraph() == rEnd
.GetParagraph() &&
145 rStart
.GetEEIndex() > rEnd
.GetEEIndex()) )
147 if( rStart
.InField() && rStart
.GetFieldOffset() )
148 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex()+1,
149 rEnd
.GetParagraph(), rEnd
.GetEEIndex() );
152 return ESelection( rStart
.GetParagraph(), rStart
.GetEEIndex(),
153 rEnd
.GetParagraph(), rEnd
.GetEEIndex() );
156 static ESelection
MakeEESelection( const SvxAccessibleTextIndex
& rIndex
)
158 return ESelection( rIndex
.GetParagraph(), rIndex
.GetEEIndex(),
159 rIndex
.GetParagraph(), rIndex
.GetEEIndex() + 1 );
162 sal_Int32
SvxAccessibleTextIndex::GetEEIndex() const
164 DBG_ASSERT(mnEEIndex
>= 0,
165 "SvxAccessibleTextIndex::GetEEIndex: index value overflow");
170 void SvxAccessibleTextIndex::SetEEIndex( sal_Int32 nEEIndex
, const SvxTextForwarder
& rTF
)
181 mnEEIndex
= nEEIndex
;
183 // calculate unknowns
184 sal_Int32 nCurrField
, nFieldCount
= rTF
.GetFieldCount( GetParagraph() );
188 EBulletInfo aBulletInfo
= rTF
.GetBulletInfo( GetParagraph() );
191 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
192 aBulletInfo
.bVisible
&&
193 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
195 mnIndex
+= aBulletInfo
.aText
.getLength();
198 for( nCurrField
=0; nCurrField
< nFieldCount
; ++nCurrField
)
200 EFieldInfo
aFieldInfo( rTF
.GetFieldInfo( GetParagraph(), nCurrField
) );
202 if( aFieldInfo
.aPosition
.nIndex
> nEEIndex
)
205 if( aFieldInfo
.aPosition
.nIndex
== nEEIndex
)
211 mnIndex
+= std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0));
215 void SvxAccessibleTextIndex::SetIndex( sal_Int32 nIndex
, const SvxTextForwarder
& rTF
)
228 // calculate unknowns
229 sal_Int32 nCurrField
, nFieldCount
= rTF
.GetFieldCount( GetParagraph() );
231 DBG_ASSERT(nIndex
>= 0,
232 "SvxAccessibleTextIndex::SetIndex: index value overflow");
236 EBulletInfo aBulletInfo
= rTF
.GetBulletInfo( GetParagraph() );
239 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
240 aBulletInfo
.bVisible
&&
241 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
243 sal_Int32 nBulletLen
= aBulletInfo
.aText
.getLength();
245 if( nIndex
< nBulletLen
)
248 SetBulletOffset( nIndex
, nBulletLen
);
253 mnEEIndex
= mnEEIndex
- nBulletLen
;
256 for( nCurrField
=0; nCurrField
< nFieldCount
; ++nCurrField
)
258 EFieldInfo
aFieldInfo( rTF
.GetFieldInfo( GetParagraph(), nCurrField
) );
260 // we're before a field
261 if( aFieldInfo
.aPosition
.nIndex
> mnEEIndex
)
264 mnEEIndex
-= std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0));
266 // we're within a field
267 if( aFieldInfo
.aPosition
.nIndex
>= mnEEIndex
)
270 SetFieldOffset( std::max(aFieldInfo
.aCurrentText
.getLength()-1, sal_Int32(0)) - (aFieldInfo
.aPosition
.nIndex
- mnEEIndex
),
271 aFieldInfo
.aCurrentText
.getLength() );
272 mnEEIndex
= aFieldInfo
.aPosition
.nIndex
;
278 bool SvxAccessibleTextIndex::IsEditableRange( const SvxAccessibleTextIndex
& rEnd
) const
280 if( GetIndex() > rEnd
.GetIndex() )
281 return rEnd
.IsEditableRange( *this );
283 if( InBullet() || rEnd
.InBullet() )
286 if( InField() && GetFieldOffset() )
287 return false; // within field
289 if( rEnd
.InField() && rEnd
.GetFieldOffset() >= rEnd
.GetFieldLen() - 1 )
290 return false; // within field
296 SvxEditSourceAdapter::SvxEditSourceAdapter() : mbEditSourceValid( false )
300 SvxEditSourceAdapter::~SvxEditSourceAdapter()
304 std::unique_ptr
<SvxEditSource
> SvxEditSourceAdapter::Clone() const
306 if( mbEditSourceValid
&& mpAdaptee
.get() )
308 std::unique_ptr
< SvxEditSource
> pClonedAdaptee( mpAdaptee
->Clone() );
312 std::unique_ptr
<SvxEditSourceAdapter
> pClone(new SvxEditSourceAdapter());
313 pClone
->SetEditSource( std::move(pClonedAdaptee
) );
314 return std::unique_ptr
< SvxEditSource
>(pClone
.release());
321 SvxAccessibleTextAdapter
* SvxEditSourceAdapter::GetTextForwarderAdapter()
323 if( mbEditSourceValid
&& mpAdaptee
.get() )
325 SvxTextForwarder
* pTextForwarder
= mpAdaptee
->GetTextForwarder();
329 maTextAdapter
.SetForwarder(*pTextForwarder
);
331 return &maTextAdapter
;
338 SvxTextForwarder
* SvxEditSourceAdapter::GetTextForwarder()
340 return GetTextForwarderAdapter();
343 SvxViewForwarder
* SvxEditSourceAdapter::GetViewForwarder()
345 if( mbEditSourceValid
&& mpAdaptee
.get() )
346 return mpAdaptee
->GetViewForwarder();
351 SvxAccessibleTextEditViewAdapter
* SvxEditSourceAdapter::GetEditViewForwarderAdapter( bool bCreate
)
353 if( mbEditSourceValid
&& mpAdaptee
.get() )
355 SvxEditViewForwarder
* pEditViewForwarder
= mpAdaptee
->GetEditViewForwarder(bCreate
);
357 if( pEditViewForwarder
)
359 SvxAccessibleTextAdapter
* pTextAdapter
= GetTextForwarderAdapter();
363 maEditViewAdapter
.SetForwarder(*pEditViewForwarder
, *pTextAdapter
);
365 return &maEditViewAdapter
;
373 SvxEditViewForwarder
* SvxEditSourceAdapter::GetEditViewForwarder( bool bCreate
)
375 return GetEditViewForwarderAdapter( bCreate
);
378 void SvxEditSourceAdapter::UpdateData()
380 if( mbEditSourceValid
&& mpAdaptee
.get() )
381 mpAdaptee
->UpdateData();
384 SfxBroadcaster
& SvxEditSourceAdapter::GetBroadcaster() const
386 if( mbEditSourceValid
&& mpAdaptee
.get() )
387 return mpAdaptee
->GetBroadcaster();
389 return maDummyBroadcaster
;
392 void SvxEditSourceAdapter::SetEditSource( std::unique_ptr
< SvxEditSource
> && pAdaptee
)
396 mpAdaptee
= std::move(pAdaptee
);
397 mbEditSourceValid
= true;
401 // do a lazy delete (prevents us from deleting the broadcaster
402 // from within a broadcast in
403 // AccessibleTextHelper_Impl::Notify)
404 mbEditSourceValid
= false;
408 SvxAccessibleTextAdapter::SvxAccessibleTextAdapter()
409 : mpTextForwarder(nullptr)
413 SvxAccessibleTextAdapter::~SvxAccessibleTextAdapter()
417 sal_Int32
SvxAccessibleTextAdapter::GetParagraphCount() const
419 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
421 return mpTextForwarder
->GetParagraphCount();
424 sal_Int32
SvxAccessibleTextAdapter::GetTextLen( sal_Int32 nParagraph
) const
426 SvxAccessibleTextIndex aIndex
;
427 aIndex
.SetEEIndex( nParagraph
, mpTextForwarder
->GetTextLen( nParagraph
), *this );
429 return aIndex
.GetIndex();
432 OUString
SvxAccessibleTextAdapter::GetText( const ESelection
& rSel
) const
434 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
436 SvxAccessibleTextIndex aStartIndex
;
437 SvxAccessibleTextIndex aEndIndex
;
439 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
440 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
442 // normalize selection
443 if( rSel
.nStartPara
> rSel
.nEndPara
||
444 (rSel
.nStartPara
== rSel
.nEndPara
&& rSel
.nStartPos
> rSel
.nEndPos
) )
446 std::swap( aStartIndex
, aEndIndex
);
449 OUString sStr
= mpTextForwarder
->GetText( MakeEESelection(aStartIndex
, aEndIndex
) );
451 // trim field text, if necessary
452 if( aStartIndex
.InField() )
454 DBG_ASSERT(aStartIndex
.GetFieldOffset() >= 0,
455 "SvxAccessibleTextIndex::GetText: index value overflow");
457 sStr
= sStr
.copy( aStartIndex
.GetFieldOffset() );
459 if( aEndIndex
.InField() && aEndIndex
.GetFieldOffset() )
461 DBG_ASSERT(sStr
.getLength() - (aEndIndex
.GetFieldLen() - aEndIndex
.GetFieldOffset()) >= 0,
462 "SvxAccessibleTextIndex::GetText: index value overflow");
464 sStr
= sStr
.copy(0, sStr
.getLength() - (aEndIndex
.GetFieldLen() - aEndIndex
.GetFieldOffset()) );
467 EBulletInfo aBulletInfo1
= GetBulletInfo( aStartIndex
.GetParagraph() );
468 EBulletInfo aBulletInfo2
= GetBulletInfo( aEndIndex
.GetParagraph() );
470 if( aEndIndex
.InBullet() )
472 // append trailing bullet
473 sStr
+= aBulletInfo2
.aText
;
475 DBG_ASSERT(sStr
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) >= 0,
476 "SvxAccessibleTextIndex::GetText: index value overflow");
478 sStr
= sStr
.copy(0, sStr
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) );
480 else if( aStartIndex
.GetParagraph() != aEndIndex
.GetParagraph() &&
481 HaveTextBullet( aEndIndex
.GetParagraph() ) )
483 OUString sBullet
= aBulletInfo2
.aText
;
485 DBG_ASSERT(sBullet
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) >= 0,
486 "SvxAccessibleTextIndex::GetText: index value overflow");
488 sBullet
= sBullet
.copy(0, sBullet
.getLength() - (aEndIndex
.GetBulletLen() - aEndIndex
.GetBulletOffset()) );
491 sStr
= sStr
.replaceAt( GetTextLen(aStartIndex
.GetParagraph()) - aStartIndex
.GetIndex(), 0, sBullet
);
497 SfxItemSet
SvxAccessibleTextAdapter::GetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
) const
499 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
501 SvxAccessibleTextIndex aStartIndex
;
502 SvxAccessibleTextIndex aEndIndex
;
504 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
505 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
507 return mpTextForwarder
->GetAttribs( MakeEESelection(aStartIndex
, aEndIndex
), nOnlyHardAttrib
);
510 SfxItemSet
SvxAccessibleTextAdapter::GetParaAttribs( sal_Int32 nPara
) const
512 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
514 return mpTextForwarder
->GetParaAttribs( nPara
);
517 void SvxAccessibleTextAdapter::SetParaAttribs( sal_Int32 nPara
, const SfxItemSet
& rSet
)
519 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
521 mpTextForwarder
->SetParaAttribs( nPara
, rSet
);
524 void SvxAccessibleTextAdapter::RemoveAttribs( const ESelection
& )
528 void SvxAccessibleTextAdapter::GetPortions( sal_Int32 nPara
, std::vector
<sal_Int32
>& rList
) const
530 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
532 mpTextForwarder
->GetPortions( nPara
, rList
);
535 SfxItemState
SvxAccessibleTextAdapter::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
537 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
539 SvxAccessibleTextIndex aStartIndex
;
540 SvxAccessibleTextIndex aEndIndex
;
542 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
543 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
545 return mpTextForwarder
->GetItemState( MakeEESelection(aStartIndex
, aEndIndex
),
549 SfxItemState
SvxAccessibleTextAdapter::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
551 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
553 return mpTextForwarder
->GetItemState( nPara
, nWhich
);
556 void SvxAccessibleTextAdapter::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
558 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
560 SvxAccessibleTextIndex aStartIndex
;
561 SvxAccessibleTextIndex aEndIndex
;
563 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
564 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
566 mpTextForwarder
->QuickInsertText( rText
,
567 MakeEESelection(aStartIndex
, aEndIndex
) );
570 void SvxAccessibleTextAdapter::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
572 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
574 SvxAccessibleTextIndex aStartIndex
;
575 SvxAccessibleTextIndex aEndIndex
;
577 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
578 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
580 mpTextForwarder
->QuickInsertField( rFld
,
581 MakeEESelection(aStartIndex
, aEndIndex
) );
584 void SvxAccessibleTextAdapter::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
586 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
588 SvxAccessibleTextIndex aStartIndex
;
589 SvxAccessibleTextIndex aEndIndex
;
591 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
592 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
594 mpTextForwarder
->QuickSetAttribs( rSet
,
595 MakeEESelection(aStartIndex
, aEndIndex
) );
598 void SvxAccessibleTextAdapter::QuickInsertLineBreak( const ESelection
& rSel
)
600 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
602 SvxAccessibleTextIndex aStartIndex
;
603 SvxAccessibleTextIndex aEndIndex
;
605 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
606 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
608 mpTextForwarder
->QuickInsertLineBreak( MakeEESelection(aStartIndex
, aEndIndex
) );
611 SfxItemPool
* SvxAccessibleTextAdapter::GetPool() const
613 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
615 return mpTextForwarder
->GetPool();
618 OUString
SvxAccessibleTextAdapter::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, boost::optional
<Color
>& rpTxtColor
, boost::optional
<Color
>& rpFldColor
)
620 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
622 return mpTextForwarder
->CalcFieldValue( rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
);
625 void SvxAccessibleTextAdapter::FieldClicked( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
)
627 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
629 mpTextForwarder
->FieldClicked( rField
, nPara
, nPos
);
632 sal_Int32
SvxAccessibleTextAdapter::CalcEditEngineIndex( sal_Int32 nPara
, sal_Int32 nLogicalIndex
)
634 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
636 SvxAccessibleTextIndex aIndex
;
637 aIndex
.SetIndex(nPara
, nLogicalIndex
, *mpTextForwarder
);
638 return aIndex
.GetEEIndex();
641 bool SvxAccessibleTextAdapter::IsValid() const
643 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
645 if( mpTextForwarder
)
646 return mpTextForwarder
->IsValid();
651 LanguageType
SvxAccessibleTextAdapter::GetLanguage( sal_Int32 nPara
, sal_Int32 nPos
) const
653 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
655 SvxAccessibleTextIndex aIndex
;
657 aIndex
.SetIndex( nPara
, nPos
, *this );
659 return mpTextForwarder
->GetLanguage( nPara
, aIndex
.GetEEIndex() );
662 sal_Int32
SvxAccessibleTextAdapter::GetFieldCount( sal_Int32 nPara
) const
664 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
666 return mpTextForwarder
->GetFieldCount( nPara
);
669 EFieldInfo
SvxAccessibleTextAdapter::GetFieldInfo( sal_Int32 nPara
, sal_uInt16 nField
) const
671 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
673 return mpTextForwarder
->GetFieldInfo( nPara
, nField
);
676 EBulletInfo
SvxAccessibleTextAdapter::GetBulletInfo( sal_Int32 nPara
) const
678 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
680 return mpTextForwarder
->GetBulletInfo( nPara
);
683 tools::Rectangle
SvxAccessibleTextAdapter::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
685 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
687 SvxAccessibleTextIndex aIndex
;
688 aIndex
.SetIndex( nPara
, nIndex
, *this );
690 // preset if anything goes wrong below
691 // n-th char in GetParagraphIndex's paragraph
692 tools::Rectangle aRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
694 if( aIndex
.InBullet() )
696 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
698 OutputDevice
* pOutDev
= GetRefDevice();
700 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
702 // preset if anything goes wrong below
703 aRect
= aBulletInfo
.aBounds
; // better than nothing
706 AccessibleStringWrap
aStringWrap( *pOutDev
, aBulletInfo
.aFont
, aBulletInfo
.aText
);
708 aStringWrap
.GetCharacterBounds( aIndex
.GetBulletOffset(), aRect
);
709 aRect
.Move( aBulletInfo
.aBounds
.Left(), aBulletInfo
.aBounds
.Top() );
714 // handle field content manually
715 if( aIndex
.InField() )
717 OutputDevice
* pOutDev
= GetRefDevice();
719 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetCharBounds: No ref device");
723 ESelection aSel
= MakeEESelection( aIndex
);
725 SvxFont aFont
= EditEngine::CreateSvxFontFromItemSet( mpTextForwarder
->GetAttribs( aSel
) );
726 AccessibleStringWrap
aStringWrap( *pOutDev
,
728 mpTextForwarder
->GetText( aSel
) );
730 tools::Rectangle aStartRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
732 aStringWrap
.GetCharacterBounds( aIndex
.GetFieldOffset(), aRect
);
733 aRect
.Move( aStartRect
.Left(), aStartRect
.Top() );
741 tools::Rectangle
SvxAccessibleTextAdapter::GetParaBounds( sal_Int32 nPara
) const
743 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
745 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
747 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
748 aBulletInfo
.bVisible
&&
749 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
751 // include bullet in para bounding box
752 tools::Rectangle
aRect( mpTextForwarder
->GetParaBounds( nPara
) );
754 aRect
.Union( aBulletInfo
.aBounds
);
759 return mpTextForwarder
->GetParaBounds( nPara
);
762 MapMode
SvxAccessibleTextAdapter::GetMapMode() const
764 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
766 return mpTextForwarder
->GetMapMode();
769 OutputDevice
* SvxAccessibleTextAdapter::GetRefDevice() const
771 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
773 return mpTextForwarder
->GetRefDevice();
776 bool SvxAccessibleTextAdapter::GetIndexAtPoint( const Point
& rPoint
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
778 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
780 if( !mpTextForwarder
->GetIndexAtPoint( rPoint
, nPara
, nIndex
) )
783 SvxAccessibleTextIndex aIndex
;
784 aIndex
.SetEEIndex(nPara
, nIndex
, *this);
786 DBG_ASSERT(aIndex
.GetIndex() >= 0,
787 "SvxAccessibleTextIndex::SetIndex: index value overflow");
789 nIndex
= aIndex
.GetIndex();
791 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
794 if( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
795 aBulletInfo
.bVisible
&&
796 aBulletInfo
.nType
!= SVX_NUM_BITMAP
)
798 if( aBulletInfo
.aBounds
.IsInside( rPoint
) )
800 OutputDevice
* pOutDev
= GetRefDevice();
802 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
807 AccessibleStringWrap
aStringWrap( *pOutDev
, aBulletInfo
.aFont
, aBulletInfo
.aText
);
809 Point aPoint
= rPoint
;
810 aPoint
.Move( -aBulletInfo
.aBounds
.Left(), -aBulletInfo
.aBounds
.Top() );
812 DBG_ASSERT(aStringWrap
.GetIndexAtPoint( aPoint
) >= 0,
813 "SvxAccessibleTextIndex::SetIndex: index value overflow");
815 nIndex
= aStringWrap
.GetIndexAtPoint( aPoint
);
820 if( aIndex
.InField() )
822 OutputDevice
* pOutDev
= GetRefDevice();
824 DBG_ASSERT(pOutDev
!=nullptr, "SvxAccessibleTextAdapter::GetIndexAtPoint: No ref device");
829 ESelection aSelection
= MakeEESelection( aIndex
);
830 SvxFont aFont
= EditEngine::CreateSvxFontFromItemSet( mpTextForwarder
->GetAttribs( aSelection
) );
831 AccessibleStringWrap
aStringWrap( *pOutDev
,
833 mpTextForwarder
->GetText( aSelection
) );
835 tools::Rectangle aRect
= mpTextForwarder
->GetCharBounds( nPara
, aIndex
.GetEEIndex() );
836 Point aPoint
= rPoint
;
837 aPoint
.Move( -aRect
.Left(), -aRect
.Top() );
839 DBG_ASSERT(aIndex
.GetIndex() + aStringWrap
.GetIndexAtPoint( rPoint
) >= 0,
840 "SvxAccessibleTextIndex::SetIndex: index value overflow");
842 nIndex
= (aIndex
.GetIndex() + aStringWrap
.GetIndexAtPoint( aPoint
));
849 bool SvxAccessibleTextAdapter::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
851 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
853 SvxAccessibleTextIndex aIndex
;
854 aIndex
.SetIndex(nPara
, nIndex
, *this);
855 nIndex
= aIndex
.GetEEIndex();
857 if( aIndex
.InBullet() )
859 DBG_ASSERT(aIndex
.GetBulletLen() >= 0,
860 "SvxAccessibleTextIndex::SetIndex: index value overflow");
862 // always treat bullet as separate word
864 nEnd
= aIndex
.GetBulletLen();
869 if( aIndex
.InField() )
871 DBG_ASSERT(aIndex
.GetIndex() - aIndex
.GetFieldOffset() >= 0 &&
872 nStart
+ aIndex
.GetFieldLen() >= 0,
873 "SvxAccessibleTextIndex::SetIndex: index value overflow");
875 // always treat field as separate word
876 // TODO: to circumvent this, _we_ would have to do the break iterator stuff!
877 nStart
= aIndex
.GetIndex() - aIndex
.GetFieldOffset();
878 nEnd
= nStart
+ aIndex
.GetFieldLen();
883 if( !mpTextForwarder
->GetWordIndices( nPara
, nIndex
, nStart
, nEnd
) )
886 aIndex
.SetEEIndex( nPara
, nStart
, *this );
887 DBG_ASSERT(aIndex
.GetIndex() >= 0,
888 "SvxAccessibleTextIndex::SetIndex: index value overflow");
889 nStart
= aIndex
.GetIndex();
891 aIndex
.SetEEIndex( nPara
, nEnd
, *this );
892 DBG_ASSERT(aIndex
.GetIndex() >= 0,
893 "SvxAccessibleTextIndex::SetIndex: index value overflow");
894 nEnd
= aIndex
.GetIndex();
899 bool SvxAccessibleTextAdapter::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool /* bInCell */ ) const
901 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
903 SvxAccessibleTextIndex aIndex
;
904 aIndex
.SetIndex(nPara
, nIndex
, *this);
905 nIndex
= aIndex
.GetEEIndex();
907 if( aIndex
.InBullet() )
909 DBG_ASSERT(aIndex
.GetBulletLen() >= 0,
910 "SvxAccessibleTextIndex::SetIndex: index value overflow");
912 // always treat bullet as distinct attribute
914 nEndIndex
= aIndex
.GetBulletLen();
919 if( aIndex
.InField() )
921 DBG_ASSERT(aIndex
.GetIndex() - aIndex
.GetFieldOffset() >= 0,
922 "SvxAccessibleTextIndex::SetIndex: index value overflow");
924 // always treat field as distinct attribute
925 nStartIndex
= aIndex
.GetIndex() - aIndex
.GetFieldOffset();
926 nEndIndex
= nStartIndex
+ aIndex
.GetFieldLen();
931 if( !mpTextForwarder
->GetAttributeRun( nStartIndex
, nEndIndex
, nPara
, nIndex
) )
934 aIndex
.SetEEIndex( nPara
, nStartIndex
, *this );
935 DBG_ASSERT(aIndex
.GetIndex() >= 0,
936 "SvxAccessibleTextIndex::SetIndex: index value overflow");
937 nStartIndex
= aIndex
.GetIndex();
939 aIndex
.SetEEIndex( nPara
, nEndIndex
, *this );
940 DBG_ASSERT(aIndex
.GetIndex() >= 0,
941 "SvxAccessibleTextIndex::SetIndex: index value overflow");
942 nEndIndex
= aIndex
.GetIndex();
947 sal_Int32
SvxAccessibleTextAdapter::GetLineCount( sal_Int32 nPara
) const
949 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
951 return mpTextForwarder
->GetLineCount( nPara
);
954 sal_Int32
SvxAccessibleTextAdapter::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
956 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
958 SvxAccessibleTextIndex aStartIndex
;
959 SvxAccessibleTextIndex aEndIndex
;
961 sal_Int32 nCurrIndex
, nLastIndex
;
962 for( nCurrLine
=0, nCurrIndex
=0, nLastIndex
=0; nCurrLine
<=nLine
; ++nCurrLine
)
964 nLastIndex
= nCurrIndex
;
966 nCurrIndex
+ mpTextForwarder
->GetLineLen( nPara
, nCurrLine
);
969 aEndIndex
.SetEEIndex( nPara
, nCurrIndex
, *this );
972 aStartIndex
.SetEEIndex( nPara
, nLastIndex
, *this );
974 return aEndIndex
.GetIndex() - aStartIndex
.GetIndex();
977 return aEndIndex
.GetIndex();
980 void SvxAccessibleTextAdapter::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nParagraph
, sal_Int32 nLine
) const
982 mpTextForwarder
->GetLineBoundaries( rStart
, rEnd
, nParagraph
, nLine
);
985 sal_Int32
SvxAccessibleTextAdapter::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
987 return mpTextForwarder
->GetLineNumberAtIndex( nPara
, nIndex
);
990 bool SvxAccessibleTextAdapter::Delete( const ESelection
& rSel
)
992 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
994 SvxAccessibleTextIndex aStartIndex
;
995 SvxAccessibleTextIndex aEndIndex
;
997 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
998 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
1000 return mpTextForwarder
->Delete( MakeEESelection(aStartIndex
, aEndIndex
) );
1003 bool SvxAccessibleTextAdapter::InsertText( const OUString
& rStr
, const ESelection
& rSel
)
1005 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1007 SvxAccessibleTextIndex aStartIndex
;
1008 SvxAccessibleTextIndex aEndIndex
;
1010 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
1011 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
1013 return mpTextForwarder
->InsertText( rStr
, MakeEESelection(aStartIndex
, aEndIndex
) );
1016 bool SvxAccessibleTextAdapter::QuickFormatDoc( bool bFull
)
1018 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1020 return mpTextForwarder
->QuickFormatDoc( bFull
);
1023 sal_Int16
SvxAccessibleTextAdapter::GetDepth( sal_Int32 nPara
) const
1025 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1027 return mpTextForwarder
->GetDepth( nPara
);
1030 bool SvxAccessibleTextAdapter::SetDepth( sal_Int32 nPara
, sal_Int16 nNewDepth
)
1032 assert(mpTextForwarder
&& "SvxAccessibleTextAdapter: no forwarder");
1034 return mpTextForwarder
->SetDepth( nPara
, nNewDepth
);
1037 void SvxAccessibleTextAdapter::SetForwarder( SvxTextForwarder
& rForwarder
)
1039 mpTextForwarder
= &rForwarder
;
1042 bool SvxAccessibleTextAdapter::HaveImageBullet( sal_Int32 nPara
) const
1044 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
1046 return ( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
1047 aBulletInfo
.bVisible
&&
1048 aBulletInfo
.nType
== SVX_NUM_BITMAP
);
1051 bool SvxAccessibleTextAdapter::HaveTextBullet( sal_Int32 nPara
) const
1053 EBulletInfo aBulletInfo
= GetBulletInfo( nPara
);
1055 return ( aBulletInfo
.nParagraph
!= EE_PARA_NOT_FOUND
&&
1056 aBulletInfo
.bVisible
&&
1057 aBulletInfo
.nType
!= SVX_NUM_BITMAP
);
1060 bool SvxAccessibleTextAdapter::IsEditable( const ESelection
& rSel
)
1062 SvxAccessibleTextIndex aStartIndex
;
1063 SvxAccessibleTextIndex aEndIndex
;
1065 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *this );
1066 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *this );
1068 // normalize selection
1069 if( rSel
.nStartPara
> rSel
.nEndPara
||
1070 (rSel
.nStartPara
== rSel
.nEndPara
&& rSel
.nStartPos
> rSel
.nEndPos
) )
1072 std::swap( aStartIndex
, aEndIndex
);
1075 return aStartIndex
.IsEditableRange( aEndIndex
);
1078 const SfxItemSet
* SvxAccessibleTextAdapter::GetEmptyItemSetPtr()
1080 OSL_FAIL( "not implemented" );
1084 void SvxAccessibleTextAdapter::AppendParagraph()
1086 OSL_FAIL( "not implemented" );
1089 sal_Int32
SvxAccessibleTextAdapter::AppendTextPortion( sal_Int32
, const OUString
&, const SfxItemSet
& )
1091 OSL_FAIL( "not implemented" );
1094 void SvxAccessibleTextAdapter::CopyText(const SvxTextForwarder
&)
1096 OSL_FAIL( "not implemented" );
1099 SvxAccessibleTextEditViewAdapter::SvxAccessibleTextEditViewAdapter()
1100 : mpViewForwarder(nullptr)
1101 , mpTextForwarder(nullptr)
1105 SvxAccessibleTextEditViewAdapter::~SvxAccessibleTextEditViewAdapter()
1109 bool SvxAccessibleTextEditViewAdapter::IsValid() const
1111 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1113 if( mpViewForwarder
)
1114 return mpViewForwarder
->IsValid();
1119 Point
SvxAccessibleTextEditViewAdapter::LogicToPixel( const Point
& rPoint
, const MapMode
& rMapMode
) const
1121 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1123 return mpViewForwarder
->LogicToPixel(rPoint
, rMapMode
);
1126 Point
SvxAccessibleTextEditViewAdapter::PixelToLogic( const Point
& rPoint
, const MapMode
& rMapMode
) const
1128 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1130 return mpViewForwarder
->PixelToLogic(rPoint
, rMapMode
);
1133 bool SvxAccessibleTextEditViewAdapter::GetSelection( ESelection
& rSel
) const
1135 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1137 ESelection aSelection
;
1139 if( !mpViewForwarder
->GetSelection( aSelection
) )
1142 SvxAccessibleTextIndex aStartIndex
;
1143 SvxAccessibleTextIndex aEndIndex
;
1145 aStartIndex
.SetEEIndex( aSelection
.nStartPara
, aSelection
.nStartPos
, *mpTextForwarder
);
1146 aEndIndex
.SetEEIndex( aSelection
.nEndPara
, aSelection
.nEndPos
, *mpTextForwarder
);
1148 DBG_ASSERT(aStartIndex
.GetIndex() >= 0 &&
1149 aEndIndex
.GetIndex() >= 0,
1150 "SvxAccessibleTextEditViewAdapter::GetSelection: index value overflow");
1152 rSel
= ESelection( aStartIndex
.GetParagraph(), aStartIndex
.GetIndex(),
1153 aEndIndex
.GetParagraph(), aEndIndex
.GetIndex() );
1158 bool SvxAccessibleTextEditViewAdapter::SetSelection( const ESelection
& rSel
)
1160 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1162 SvxAccessibleTextIndex aStartIndex
;
1163 SvxAccessibleTextIndex aEndIndex
;
1165 aStartIndex
.SetIndex( rSel
.nStartPara
, rSel
.nStartPos
, *mpTextForwarder
);
1166 aEndIndex
.SetIndex( rSel
.nEndPara
, rSel
.nEndPos
, *mpTextForwarder
);
1168 return mpViewForwarder
->SetSelection( MakeEESelection(aStartIndex
, aEndIndex
) );
1171 bool SvxAccessibleTextEditViewAdapter::Copy()
1173 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1175 return mpViewForwarder
->Copy();
1178 bool SvxAccessibleTextEditViewAdapter::Cut()
1180 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1182 return mpViewForwarder
->Cut();
1185 bool SvxAccessibleTextEditViewAdapter::Paste()
1187 DBG_ASSERT(mpViewForwarder
, "SvxAccessibleTextEditViewAdapter: no forwarder");
1189 return mpViewForwarder
->Paste();
1192 void SvxAccessibleTextEditViewAdapter::SetForwarder( SvxEditViewForwarder
& rForwarder
,
1193 SvxAccessibleTextAdapter
& rTextForwarder
)
1195 mpViewForwarder
= &rForwarder
;
1196 mpTextForwarder
= &rTextForwarder
;
1199 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */