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 .
21 #include <osl/diagnose.h>
22 #include <tools/debug.hxx>
23 #include <editeng/eeitem.hxx>
24 #include <com/sun/star/i18n/WordType.hpp>
26 #include <svl/itemset.hxx>
27 #include <editeng/editeng.hxx>
28 #include <editeng/unoedhlp.hxx>
29 #include <editeng/editdata.hxx>
30 #include <editeng/outliner.hxx>
31 #include <editeng/editobj.hxx>
33 #include <editeng/unofored.hxx>
34 #include "unofored_internal.hxx"
36 using namespace ::com::sun::star
;
39 SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine
& rEngine
) :
40 rEditEngine( rEngine
)
44 SvxEditEngineForwarder::~SvxEditEngineForwarder()
46 // the EditEngine may need to be deleted from the outside
49 sal_Int32
SvxEditEngineForwarder::GetParagraphCount() const
51 return rEditEngine
.GetParagraphCount();
54 sal_Int32
SvxEditEngineForwarder::GetTextLen( sal_Int32 nParagraph
) const
56 return rEditEngine
.GetTextLen( nParagraph
);
59 OUString
SvxEditEngineForwarder::GetText( const ESelection
& rSel
) const
61 return convertLineEnd(rEditEngine
.GetText(rSel
), GetSystemLineEnd());
64 SfxItemSet
SvxEditEngineForwarder::GetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
) const
66 if( rSel
.nStartPara
== rSel
.nEndPara
)
68 GetAttribsFlags nFlags
= GetAttribsFlags::NONE
;
69 switch( nOnlyHardAttrib
)
71 case EditEngineAttribs::All
:
72 nFlags
= GetAttribsFlags::ALL
;
74 case EditEngineAttribs::OnlyHard
:
75 nFlags
= GetAttribsFlags::CHARATTRIBS
;
78 OSL_FAIL("unknown flags for SvxOutlinerForwarder::GetAttribs");
81 return rEditEngine
.GetAttribs( rSel
.nStartPara
, rSel
.nStartPos
, rSel
.nEndPos
, nFlags
);
85 return rEditEngine
.GetAttribs( rSel
, nOnlyHardAttrib
);
89 SfxItemSet
SvxEditEngineForwarder::GetParaAttribs( sal_Int32 nPara
) const
91 SfxItemSet
aSet( rEditEngine
.GetParaAttribs( nPara
) );
93 sal_uInt16 nWhich
= EE_PARA_START
;
94 while( nWhich
<= EE_PARA_END
)
96 if( aSet
.GetItemState( nWhich
) != SfxItemState::SET
)
98 if( rEditEngine
.HasParaAttrib( nPara
, nWhich
) )
99 aSet
.Put( rEditEngine
.GetParaAttrib( nPara
, nWhich
) );
107 void SvxEditEngineForwarder::SetParaAttribs( sal_Int32 nPara
, const SfxItemSet
& rSet
)
109 rEditEngine
.SetParaAttribs( nPara
, rSet
);
112 void SvxEditEngineForwarder::RemoveAttribs( const ESelection
& rSelection
)
114 rEditEngine
.RemoveAttribs( rSelection
, false/*bRemoveParaAttribs*/, 0 );
117 SfxItemPool
* SvxEditEngineForwarder::GetPool() const
119 return rEditEngine
.GetEmptyItemSet().GetPool();
122 void SvxEditEngineForwarder::GetPortions( sal_Int32 nPara
, std::vector
<sal_Int32
>& rList
) const
124 rEditEngine
.GetPortions( nPara
, rList
);
127 void SvxEditEngineForwarder::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
129 rEditEngine
.QuickInsertText( rText
, rSel
);
132 void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection
& rSel
)
134 rEditEngine
.QuickInsertLineBreak( rSel
);
137 void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
139 rEditEngine
.QuickInsertField( rFld
, rSel
);
142 void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
144 rEditEngine
.QuickSetAttribs( rSet
, rSel
);
147 bool SvxEditEngineForwarder::IsValid() const
149 // cannot reliably query EditEngine state
150 // while in the middle of an update
151 return rEditEngine
.GetUpdateMode();
154 OUString
SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, std::optional
<Color
>& rpTxtColor
, std::optional
<Color
>& rpFldColor
)
156 return rEditEngine
.CalcFieldValue( rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
);
159 void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem
& rField
)
161 rEditEngine
.FieldClicked( rField
);
164 SfxItemState
GetSvxEditEngineItemState( EditEngine
const & rEditEngine
, const ESelection
& rSel
, sal_uInt16 nWhich
)
166 std::vector
<EECharAttrib
> aAttribs
;
168 const SfxPoolItem
* pLastItem
= nullptr;
170 SfxItemState eState
= SfxItemState::DEFAULT
;
172 // check all paragraphs inside the selection
173 for( sal_Int32 nPara
= rSel
.nStartPara
; nPara
<= rSel
.nEndPara
; nPara
++ )
175 SfxItemState eParaState
= SfxItemState::DEFAULT
;
177 // calculate start and endpos for this paragraph
179 if( rSel
.nStartPara
== nPara
)
180 nPos
= rSel
.nStartPos
;
182 sal_Int32 nEndPos
= rSel
.nEndPos
;
183 if( rSel
.nEndPara
!= nPara
)
184 nEndPos
= rEditEngine
.GetTextLen( nPara
);
187 // get list of char attribs
188 rEditEngine
.GetCharAttribs( nPara
, aAttribs
);
190 bool bEmpty
= true; // we found no item inside the selection of this paragraph
191 bool bGaps
= false; // we found items but there are gaps between them
192 sal_Int32 nLastEnd
= nPos
;
194 const SfxPoolItem
* pParaItem
= nullptr;
196 for (auto const& attrib
: aAttribs
)
198 DBG_ASSERT(attrib
.pAttr
, "GetCharAttribs gives corrupt data");
200 const bool bEmptyPortion
= attrib
.nStart
== attrib
.nEnd
;
201 if((!bEmptyPortion
&& attrib
.nStart
>= nEndPos
) ||
202 (bEmptyPortion
&& attrib
.nStart
> nEndPos
))
203 break; // break if we are already behind our selection
205 if((!bEmptyPortion
&& attrib
.nEnd
<= nPos
) ||
206 (bEmptyPortion
&& attrib
.nEnd
< nPos
))
207 continue; // or if the attribute ends before our selection
209 if(attrib
.pAttr
->Which() != nWhich
)
210 continue; // skip if is not the searched item
212 // if we already found an item
215 // ... and its different to this one than the state is don't care
216 if(*pParaItem
!= *(attrib
.pAttr
))
217 return SfxItemState::DONTCARE
;
220 pParaItem
= attrib
.pAttr
;
225 if(!bGaps
&& attrib
.nStart
> nLastEnd
)
228 nLastEnd
= attrib
.nEnd
;
231 if( !bEmpty
&& !bGaps
&& nLastEnd
< ( nEndPos
- 1 ) )
235 eParaState
= SfxItemState::DEFAULT
;
237 eParaState
= SfxItemState::DONTCARE
;
239 eParaState
= SfxItemState::SET
;
241 // if we already found an item check if we found the same
244 if( (pParaItem
== nullptr) || (*pLastItem
!= *pParaItem
) )
245 return SfxItemState::DONTCARE
;
249 pLastItem
= pParaItem
;
257 SfxItemState
SvxEditEngineForwarder::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
259 return GetSvxEditEngineItemState( rEditEngine
, rSel
, nWhich
);
262 SfxItemState
SvxEditEngineForwarder::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
264 const SfxItemSet
& rSet
= rEditEngine
.GetParaAttribs( nPara
);
265 return rSet
.GetItemState( nWhich
);
268 LanguageType
SvxEditEngineForwarder::GetLanguage( sal_Int32 nPara
, sal_Int32 nIndex
) const
270 return rEditEngine
.GetLanguage(nPara
, nIndex
);
273 sal_Int32
SvxEditEngineForwarder::GetFieldCount( sal_Int32 nPara
) const
275 return rEditEngine
.GetFieldCount(nPara
);
278 EFieldInfo
SvxEditEngineForwarder::GetFieldInfo( sal_Int32 nPara
, sal_uInt16 nField
) const
280 return rEditEngine
.GetFieldInfo( nPara
, nField
);
283 EBulletInfo
SvxEditEngineForwarder::GetBulletInfo( sal_Int32
) const
285 return EBulletInfo();
288 tools::Rectangle
SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
290 // EditEngine's 'internal' methods like GetCharacterBounds()
291 // don't rotate for vertical text.
292 Size
aSize( rEditEngine
.CalcTextWidth(), rEditEngine
.GetTextHeight() );
293 // swap width and height
294 tools::Long tmp
= aSize
.Width();
295 aSize
.setWidth(aSize
.Height());
296 aSize
.setHeight(tmp
);
297 bool bIsVertical( rEditEngine
.IsVertical() );
299 // #108900# Handle virtual position one-past-the end of the string
300 if( nIndex
>= rEditEngine
.GetTextLen(nPara
) )
302 tools::Rectangle aLast
;
306 // use last character, if possible
307 aLast
= rEditEngine
.GetCharacterBounds( EPosition(nPara
, nIndex
-1) );
309 // move at end of this last character, make one pixel wide
310 aLast
.Move( aLast
.Right() - aLast
.Left(), 0 );
311 aLast
.SetSize( Size(1, aLast
.GetHeight()) );
314 aLast
= SvxEditSourceHelper::EEToUserSpace( aLast
, aSize
, bIsVertical
);
318 // #109864# Bounds must lie within the paragraph
319 aLast
= GetParaBounds( nPara
);
321 // #109151# Don't use paragraph height, but line height
322 // instead. aLast is already CTL-correct
324 aLast
.SetSize( Size( rEditEngine
.GetLineHeight(nPara
), 1 ) );
326 aLast
.SetSize( Size( 1, rEditEngine
.GetLineHeight(nPara
) ) );
333 return SvxEditSourceHelper::EEToUserSpace( rEditEngine
.GetCharacterBounds( EPosition(nPara
, nIndex
) ),
334 aSize
, bIsVertical
);
338 tools::Rectangle
SvxEditEngineForwarder::GetParaBounds( sal_Int32 nPara
) const
340 const Point aPnt
= rEditEngine
.GetDocPosTopLeft( nPara
);
344 if( rEditEngine
.IsVertical() )
346 // Hargl. EditEngine's 'external' methods return the rotated
347 // dimensions, 'internal' methods like GetTextHeight( n )
349 nWidth
= rEditEngine
.GetTextHeight( nPara
);
350 nHeight
= rEditEngine
.GetTextHeight();
351 sal_uLong nTextWidth
= rEditEngine
.GetTextHeight();
353 return tools::Rectangle( nTextWidth
- aPnt
.Y() - nWidth
, 0, nTextWidth
- aPnt
.Y(), nHeight
);
357 nWidth
= rEditEngine
.CalcTextWidth();
358 nHeight
= rEditEngine
.GetTextHeight( nPara
);
360 return tools::Rectangle( 0, aPnt
.Y(), nWidth
, aPnt
.Y() + nHeight
);
364 MapMode
SvxEditEngineForwarder::GetMapMode() const
366 return rEditEngine
.GetRefMapMode();
369 OutputDevice
* SvxEditEngineForwarder::GetRefDevice() const
371 return rEditEngine
.GetRefDevice();
374 bool SvxEditEngineForwarder::GetIndexAtPoint( const Point
& rPos
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
376 Size
aSize( rEditEngine
.CalcTextWidth(), rEditEngine
.GetTextHeight() );
377 // swap width and height
378 tools::Long tmp
= aSize
.Width();
379 aSize
.setWidth(aSize
.Height());
380 aSize
.setHeight(tmp
);
381 Point
aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos
,
383 rEditEngine
.IsVertical() ));
385 EPosition aDocPos
= rEditEngine
.FindDocPosition( aEEPos
);
387 nPara
= aDocPos
.nPara
;
388 nIndex
= aDocPos
.nIndex
;
393 bool SvxEditEngineForwarder::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
395 ESelection aRes
= rEditEngine
.GetWord( ESelection(nPara
, nIndex
, nPara
, nIndex
), css::i18n::WordType::DICTIONARY_WORD
);
397 if( aRes
.nStartPara
== nPara
&&
398 aRes
.nStartPara
== aRes
.nEndPara
)
400 nStart
= aRes
.nStartPos
;
409 bool SvxEditEngineForwarder::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool bInCell
) const
411 SvxEditSourceHelper::GetAttributeRun( nStartIndex
, nEndIndex
, rEditEngine
, nPara
, nIndex
, bInCell
);
415 sal_Int32
SvxEditEngineForwarder::GetLineCount( sal_Int32 nPara
) const
417 return rEditEngine
.GetLineCount(nPara
);
420 sal_Int32
SvxEditEngineForwarder::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
422 return rEditEngine
.GetLineLen(nPara
, nLine
);
425 void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nPara
, sal_Int32 nLine
) const
427 rEditEngine
.GetLineBoundaries(rStart
, rEnd
, nPara
, nLine
);
430 sal_Int32
SvxEditEngineForwarder::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
432 return rEditEngine
.GetLineNumberAtIndex(nPara
, nIndex
);
436 bool SvxEditEngineForwarder::QuickFormatDoc( bool )
438 rEditEngine
.QuickFormatDoc();
443 bool SvxEditEngineForwarder::Delete( const ESelection
& rSelection
)
445 rEditEngine
.QuickDelete( rSelection
);
446 rEditEngine
.QuickFormatDoc();
451 bool SvxEditEngineForwarder::InsertText( const OUString
& rStr
, const ESelection
& rSelection
)
453 rEditEngine
.QuickInsertText( rStr
, rSelection
);
454 rEditEngine
.QuickFormatDoc();
459 sal_Int16
SvxEditEngineForwarder::GetDepth( sal_Int32
) const
461 // EditEngine does not support outline depth
465 bool SvxEditEngineForwarder::SetDepth( sal_Int32
, sal_Int16 nNewDepth
)
467 // EditEngine does not support outline depth
468 return nNewDepth
== -1;
471 const SfxItemSet
* SvxEditEngineForwarder::GetEmptyItemSetPtr()
473 return &rEditEngine
.GetEmptyItemSet();
476 void SvxEditEngineForwarder::AppendParagraph()
478 rEditEngine
.InsertParagraph( rEditEngine
.GetParagraphCount(), OUString() );
481 sal_Int32
SvxEditEngineForwarder::AppendTextPortion( sal_Int32 nPara
, const OUString
&rText
, const SfxItemSet
& /*rSet*/ )
485 sal_Int32 nParaCount
= rEditEngine
.GetParagraphCount();
486 DBG_ASSERT( nPara
< nParaCount
, "paragraph index out of bounds" );
487 if (0 <= nPara
&& nPara
< nParaCount
)
489 nLen
= rEditEngine
.GetTextLen( nPara
);
490 rEditEngine
.QuickInsertText( rText
, ESelection( nPara
, nLen
, nPara
, nLen
) );
496 void SvxEditEngineForwarder::CopyText(const SvxTextForwarder
& rSource
)
498 const SvxEditEngineForwarder
* pSourceForwarder
= dynamic_cast< const SvxEditEngineForwarder
* >( &rSource
);
499 if( !pSourceForwarder
)
501 std::unique_ptr
<EditTextObject
> pNewTextObject
= pSourceForwarder
->rEditEngine
.CreateTextObject();
502 rEditEngine
.SetText( *pNewTextObject
);
506 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */