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
.start
.nPara
== rSel
.end
.nPara
)
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
.start
.nPara
, rSel
.start
.nIndex
, rSel
.end
.nIndex
, 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 OUString
SvxEditEngineForwarder::GetStyleSheet(sal_Int32 nPara
) const
129 if (auto pStyle
= rEditEngine
.GetStyleSheet(nPara
))
130 return pStyle
->GetName();
134 void SvxEditEngineForwarder::SetStyleSheet(sal_Int32 nPara
, const OUString
& rStyleName
)
136 auto pStyleSheetPool
= rEditEngine
.GetStyleSheetPool();
137 if (auto pStyle
= pStyleSheetPool
? pStyleSheetPool
->Find(rStyleName
, SfxStyleFamily::Para
) : nullptr)
138 rEditEngine
.SetStyleSheet(nPara
, static_cast<SfxStyleSheet
*>(pStyle
));
141 void SvxEditEngineForwarder::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
143 rEditEngine
.QuickInsertText( rText
, rSel
);
146 void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection
& rSel
)
148 rEditEngine
.QuickInsertLineBreak( rSel
);
151 void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
153 rEditEngine
.QuickInsertField( rFld
, rSel
);
156 void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
158 rEditEngine
.QuickSetAttribs( rSet
, rSel
);
161 bool SvxEditEngineForwarder::IsValid() const
163 // cannot reliably query EditEngine state
164 // while in the middle of an update
165 return rEditEngine
.IsUpdateLayout();
168 OUString
SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, std::optional
<Color
>& rpTxtColor
, std::optional
<Color
>& rpFldColor
, std::optional
<FontLineStyle
>& rpFldLineStyle
)
170 return rEditEngine
.CalcFieldValue( rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
, rpFldLineStyle
);
173 void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem
& rField
)
175 rEditEngine
.FieldClicked( rField
);
178 SfxItemState
GetSvxEditEngineItemState( EditEngine
const & rEditEngine
, const ESelection
& rSel
, sal_uInt16 nWhich
)
180 std::vector
<EECharAttrib
> aAttribs
;
182 const SfxPoolItem
* pLastItem
= nullptr;
184 SfxItemState eState
= SfxItemState::DEFAULT
;
186 // check all paragraphs inside the selection
187 for (sal_Int32 nPara
= rSel
.start
.nPara
; nPara
<= rSel
.end
.nPara
; nPara
++)
189 SfxItemState eParaState
= SfxItemState::DEFAULT
;
191 // calculate start and endpos for this paragraph
193 if (rSel
.start
.nPara
== nPara
)
194 nPos
= rSel
.start
.nIndex
;
196 sal_Int32 nEndPos
= rSel
.end
.nIndex
;
197 if (rSel
.end
.nPara
!= nPara
)
198 nEndPos
= rEditEngine
.GetTextLen( nPara
);
201 // get list of char attribs
202 rEditEngine
.GetCharAttribs( nPara
, aAttribs
);
204 bool bEmpty
= true; // we found no item inside the selection of this paragraph
205 bool bGaps
= false; // we found items but there are gaps between them
206 sal_Int32 nLastEnd
= nPos
;
208 const SfxPoolItem
* pParaItem
= nullptr;
210 for (auto const& attrib
: aAttribs
)
212 assert(attrib
.pAttr
&& "GetCharAttribs gives corrupt data");
214 const bool bEmptyPortion
= attrib
.nStart
== attrib
.nEnd
;
215 if((!bEmptyPortion
&& attrib
.nStart
>= nEndPos
) ||
216 (bEmptyPortion
&& attrib
.nStart
> nEndPos
))
217 break; // break if we are already behind our selection
219 if((!bEmptyPortion
&& attrib
.nEnd
<= nPos
) ||
220 (bEmptyPortion
&& attrib
.nEnd
< nPos
))
221 continue; // or if the attribute ends before our selection
223 if(attrib
.pAttr
->Which() != nWhich
)
224 continue; // skip if is not the searched item
226 // if we already found an item
229 // ... and its different to this one than the state is don't care
230 if(*pParaItem
!= *(attrib
.pAttr
))
231 return SfxItemState::INVALID
;
234 pParaItem
= attrib
.pAttr
;
239 if(!bGaps
&& attrib
.nStart
> nLastEnd
)
242 nLastEnd
= attrib
.nEnd
;
245 if( !bEmpty
&& !bGaps
&& nLastEnd
< ( nEndPos
- 1 ) )
249 eParaState
= SfxItemState::DEFAULT
;
251 eParaState
= SfxItemState::INVALID
;
253 eParaState
= SfxItemState::SET
;
255 // if we already found an item check if we found the same
258 if( (pParaItem
== nullptr) || (*pLastItem
!= *pParaItem
) )
259 return SfxItemState::INVALID
;
263 pLastItem
= pParaItem
;
271 SfxItemState
SvxEditEngineForwarder::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
273 return GetSvxEditEngineItemState( rEditEngine
, rSel
, nWhich
);
276 SfxItemState
SvxEditEngineForwarder::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
278 const SfxItemSet
& rSet
= rEditEngine
.GetParaAttribs( nPara
);
279 return rSet
.GetItemState( nWhich
);
282 LanguageType
SvxEditEngineForwarder::GetLanguage( sal_Int32 nPara
, sal_Int32 nIndex
) const
284 return rEditEngine
.GetLanguage(nPara
, nIndex
).nLang
;
287 std::vector
<EFieldInfo
> SvxEditEngineForwarder::GetFieldInfo( sal_Int32 nPara
) const
289 return rEditEngine
.GetFieldInfo( nPara
);
292 EBulletInfo
SvxEditEngineForwarder::GetBulletInfo( sal_Int32
) const
294 return EBulletInfo();
297 tools::Rectangle
SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
299 // EditEngine's 'internal' methods like GetCharacterBounds()
300 // don't rotate for vertical text.
301 Size
aSize( rEditEngine
.CalcTextWidth(), rEditEngine
.GetTextHeight() );
302 // swap width and height
303 tools::Long tmp
= aSize
.Width();
304 aSize
.setWidth(aSize
.Height());
305 aSize
.setHeight(tmp
);
306 bool bIsVertical( rEditEngine
.IsEffectivelyVertical() );
308 // #108900# Handle virtual position one-past-the end of the string
309 if( nIndex
>= rEditEngine
.GetTextLen(nPara
) )
311 tools::Rectangle aLast
;
315 // use last character, if possible
316 aLast
= rEditEngine
.GetCharacterBounds(EPaM(nPara
, nIndex
- 1));
318 // move at end of this last character, make one pixel wide
319 aLast
.Move( aLast
.Right() - aLast
.Left(), 0 );
320 aLast
.SetSize( Size(1, aLast
.GetHeight()) );
323 aLast
= SvxEditSourceHelper::EEToUserSpace( aLast
, aSize
, bIsVertical
);
327 // #109864# Bounds must lie within the paragraph
328 aLast
= GetParaBounds( nPara
);
330 // #109151# Don't use paragraph height, but line height
331 // instead. aLast is already CTL-correct
333 aLast
.SetSize( Size( rEditEngine
.GetLineHeight(nPara
), 1 ) );
335 aLast
.SetSize( Size( 1, rEditEngine
.GetLineHeight(nPara
) ) );
342 return SvxEditSourceHelper::EEToUserSpace( rEditEngine
.GetCharacterBounds( EPaM(nPara
, nIndex
) ),
343 aSize
, bIsVertical
);
347 tools::Rectangle
SvxEditEngineForwarder::GetParaBounds( sal_Int32 nPara
) const
349 const Point aPnt
= rEditEngine
.GetDocPosTopLeft( nPara
);
353 if( rEditEngine
.IsEffectivelyVertical() )
355 // Hargl. EditEngine's 'external' methods return the rotated
356 // dimensions, 'internal' methods like GetTextHeight( n )
358 nWidth
= rEditEngine
.GetTextHeight( nPara
);
359 nHeight
= rEditEngine
.GetTextHeight();
360 sal_uInt32 nTextWidth
= rEditEngine
.GetTextHeight();
362 return tools::Rectangle( nTextWidth
- aPnt
.Y() - nWidth
, 0, nTextWidth
- aPnt
.Y(), nHeight
);
366 nWidth
= rEditEngine
.CalcTextWidth();
367 nHeight
= rEditEngine
.GetTextHeight( nPara
);
369 return tools::Rectangle( 0, aPnt
.Y(), nWidth
, aPnt
.Y() + nHeight
);
373 MapMode
SvxEditEngineForwarder::GetMapMode() const
375 return rEditEngine
.GetRefMapMode();
378 OutputDevice
* SvxEditEngineForwarder::GetRefDevice() const
380 return rEditEngine
.GetRefDevice();
383 bool SvxEditEngineForwarder::GetIndexAtPoint( const Point
& rPos
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
385 Size
aSize( rEditEngine
.CalcTextWidth(), rEditEngine
.GetTextHeight() );
386 // swap width and height
387 tools::Long tmp
= aSize
.Width();
388 aSize
.setWidth(aSize
.Height());
389 aSize
.setHeight(tmp
);
390 Point
aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos
,
392 rEditEngine
.IsEffectivelyVertical() ));
394 EPaM aDocPos
= rEditEngine
.FindDocPosition(aEEPos
);
396 nPara
= aDocPos
.nPara
;
397 nIndex
= aDocPos
.nIndex
;
402 bool SvxEditEngineForwarder::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
404 ESelection aRes
= rEditEngine
.GetWord( ESelection(nPara
, nIndex
, nPara
, nIndex
), css::i18n::WordType::DICTIONARY_WORD
);
406 if( aRes
.start
.nPara
== nPara
&&
407 aRes
.start
.nPara
== aRes
.end
.nPara
)
409 nStart
= aRes
.start
.nIndex
;
410 nEnd
= aRes
.end
.nIndex
;
418 bool SvxEditEngineForwarder::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool bInCell
) const
420 SvxEditSourceHelper::GetAttributeRun( nStartIndex
, nEndIndex
, rEditEngine
, nPara
, nIndex
, bInCell
);
424 sal_Int32
SvxEditEngineForwarder::GetLineCount( sal_Int32 nPara
) const
426 return rEditEngine
.GetLineCount(nPara
);
429 sal_Int32
SvxEditEngineForwarder::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
431 return rEditEngine
.GetLineLen(nPara
, nLine
);
434 void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nPara
, sal_Int32 nLine
) const
436 rEditEngine
.GetLineBoundaries(rStart
, rEnd
, nPara
, nLine
);
439 sal_Int32
SvxEditEngineForwarder::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
441 return rEditEngine
.GetLineNumberAtIndex(nPara
, nIndex
);
445 bool SvxEditEngineForwarder::QuickFormatDoc( bool )
447 rEditEngine
.QuickFormatDoc();
452 bool SvxEditEngineForwarder::Delete( const ESelection
& rSelection
)
454 rEditEngine
.QuickDelete( rSelection
);
455 rEditEngine
.QuickFormatDoc();
460 bool SvxEditEngineForwarder::InsertText( const OUString
& rStr
, const ESelection
& rSelection
)
462 rEditEngine
.QuickInsertText( rStr
, rSelection
);
463 rEditEngine
.QuickFormatDoc();
468 bool SvxEditEngineForwarder::SupportsOutlineDepth() const
470 // EditEngine does not support outline depth indirectly - directly supports EE_PARA_OUTLLEVEL
474 sal_Int16
SvxEditEngineForwarder::GetDepth( sal_Int32
) const
476 // EditEngine does not support outline depth
480 bool SvxEditEngineForwarder::SetDepth( sal_Int32
, sal_Int16 nNewDepth
)
482 // EditEngine does not support outline depth
483 return nNewDepth
== -1;
486 const SfxItemSet
* SvxEditEngineForwarder::GetEmptyItemSetPtr()
488 return &rEditEngine
.GetEmptyItemSet();
491 void SvxEditEngineForwarder::AppendParagraph()
493 rEditEngine
.InsertParagraph( rEditEngine
.GetParagraphCount(), OUString() );
496 sal_Int32
SvxEditEngineForwarder::AppendTextPortion( sal_Int32 nPara
, const OUString
&rText
, const SfxItemSet
& /*rSet*/ )
500 sal_Int32 nParaCount
= rEditEngine
.GetParagraphCount();
501 DBG_ASSERT( nPara
< nParaCount
, "paragraph index out of bounds" );
502 if (0 <= nPara
&& nPara
< nParaCount
)
504 nLen
= rEditEngine
.GetTextLen( nPara
);
505 rEditEngine
.QuickInsertText(rText
, ESelection(nPara
, nLen
));
511 void SvxEditEngineForwarder::CopyText(const SvxTextForwarder
& rSource
)
513 const SvxEditEngineForwarder
* pSourceForwarder
= dynamic_cast< const SvxEditEngineForwarder
* >( &rSource
);
514 if( !pSourceForwarder
)
516 std::unique_ptr
<EditTextObject
> pNewTextObject
= pSourceForwarder
->rEditEngine
.CreateTextObject();
517 rEditEngine
.SetText( *pNewTextObject
);
521 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */