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 <svl/style.hxx>
24 #include <com/sun/star/i18n/WordType.hpp>
26 #include <svl/itemset.hxx>
27 #include <editeng/editeng.hxx>
28 #include <editeng/editdata.hxx>
29 #include <editeng/outliner.hxx>
30 #include <editeng/unoedhlp.hxx>
31 #include <svl/poolitem.hxx>
33 #include <editeng/unoforou.hxx>
34 #include <editeng/outlobj.hxx>
35 #include "unofored_internal.hxx"
37 using namespace ::com::sun::star
;
40 SvxOutlinerForwarder::SvxOutlinerForwarder( Outliner
& rOutl
, bool bOutlText
/* = false */ ) :
42 bOutlinerText( bOutlText
),
43 mnParaAttribsCache( 0 )
47 SvxOutlinerForwarder::~SvxOutlinerForwarder()
52 sal_Int32
SvxOutlinerForwarder::GetParagraphCount() const
54 return rOutliner
.GetParagraphCount();
57 sal_Int32
SvxOutlinerForwarder::GetTextLen( sal_Int32 nParagraph
) const
59 return rOutliner
.GetEditEngine().GetTextLen( nParagraph
);
62 OUString
SvxOutlinerForwarder::GetText( const ESelection
& rSel
) const
64 //! GetText (ESelection) should probably also be in the Outliner
65 // in the time being use as the hack for the EditEngine:
66 EditEngine
* pEditEngine
= const_cast<EditEngine
*>(&rOutliner
.GetEditEngine());
67 return pEditEngine
->GetText( rSel
);
70 static SfxItemSet
ImplOutlinerForwarderGetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
, EditEngine
& rEditEngine
)
72 if (rSel
.start
.nPara
== rSel
.end
.nPara
)
74 GetAttribsFlags nFlags
= GetAttribsFlags::NONE
;
76 switch( nOnlyHardAttrib
)
78 case EditEngineAttribs::All
:
79 nFlags
= GetAttribsFlags::ALL
;
81 case EditEngineAttribs::OnlyHard
:
82 nFlags
= GetAttribsFlags::CHARATTRIBS
;
85 OSL_FAIL("unknown flags for SvxOutlinerForwarder::GetAttribs");
87 return rEditEngine
.GetAttribs( rSel
.start
.nPara
, rSel
.start
.nIndex
, rSel
.end
.nIndex
, nFlags
);
91 return rEditEngine
.GetAttribs( rSel
, nOnlyHardAttrib
);
95 SfxItemSet
SvxOutlinerForwarder::GetAttribs( const ESelection
& rSel
, EditEngineAttribs nOnlyHardAttrib
) const
97 if( moAttribsCache
&& ( EditEngineAttribs::All
== nOnlyHardAttrib
) )
99 // have we the correct set in cache?
100 if( maAttribCacheSelection
== rSel
)
102 // yes! just return the cache
103 return *moAttribsCache
;
107 // no, we need delete the old cache
108 moAttribsCache
.reset();
112 //! Does it not exist on the Outliner?
113 //! and why is the GetAttribs on the EditEngine not a const?
114 EditEngine
& rEditEngine
= const_cast<EditEngine
&>(rOutliner
.GetEditEngine());
116 SfxItemSet
aSet( ImplOutlinerForwarderGetAttribs( rSel
, nOnlyHardAttrib
, rEditEngine
) );
118 if( EditEngineAttribs::All
== nOnlyHardAttrib
)
120 moAttribsCache
.emplace( aSet
);
121 maAttribCacheSelection
= rSel
;
124 SfxStyleSheet
* pStyle
= rEditEngine
.GetStyleSheet(rSel
.start
.nPara
);
126 aSet
.SetParent( &(pStyle
->GetItemSet() ) );
131 SfxItemSet
SvxOutlinerForwarder::GetParaAttribs( sal_Int32 nPara
) const
133 if( moParaAttribsCache
)
135 // have we the correct set in cache?
136 if( nPara
== mnParaAttribsCache
)
138 // yes! just return the cache
139 return *moParaAttribsCache
;
143 // no, we need delete the old cache
144 moParaAttribsCache
.reset();
148 moParaAttribsCache
.emplace( rOutliner
.GetParaAttribs( nPara
) );
149 mnParaAttribsCache
= nPara
;
151 EditEngine
& rEditEngine
= const_cast<EditEngine
&>(rOutliner
.GetEditEngine());
153 SfxStyleSheet
* pStyle
= rEditEngine
.GetStyleSheet( nPara
);
155 moParaAttribsCache
->SetParent( &(pStyle
->GetItemSet() ) );
157 return *moParaAttribsCache
;
160 void SvxOutlinerForwarder::SetParaAttribs( sal_Int32 nPara
, const SfxItemSet
& rSet
)
164 const SfxItemSet
* pOldParent
= rSet
.GetParent();
166 const_cast<SfxItemSet
*>(&rSet
)->SetParent( nullptr );
168 rOutliner
.SetParaAttribs( nPara
, rSet
);
171 const_cast<SfxItemSet
*>(&rSet
)->SetParent( pOldParent
);
174 void SvxOutlinerForwarder::RemoveAttribs( const ESelection
& rSelection
)
176 rOutliner
.RemoveAttribs( rSelection
, false/*bRemoveParaAttribs*/, 0 );
179 SfxItemPool
* SvxOutlinerForwarder::GetPool() const
181 return rOutliner
.GetEmptyItemSet().GetPool();
184 void SvxOutlinerForwarder::GetPortions( sal_Int32 nPara
, std::vector
<sal_Int32
>& rList
) const
186 const_cast<EditEngine
&>(rOutliner
.GetEditEngine()).GetPortions( nPara
, rList
);
189 OUString
SvxOutlinerForwarder::GetStyleSheet(sal_Int32 nPara
) const
191 if (auto pStyle
= rOutliner
.GetStyleSheet(nPara
))
192 return pStyle
->GetName();
196 void SvxOutlinerForwarder::SetStyleSheet(sal_Int32 nPara
, const OUString
& rStyleName
)
198 auto pStyleSheetPool
= rOutliner
.GetStyleSheetPool();
199 if (auto pStyle
= pStyleSheetPool
? pStyleSheetPool
->Find(rStyleName
, SfxStyleFamily::Para
) : nullptr)
200 rOutliner
.SetStyleSheet(nPara
, static_cast<SfxStyleSheet
*>(pStyle
));
203 void SvxOutlinerForwarder::QuickInsertText( const OUString
& rText
, const ESelection
& rSel
)
206 if( rText
.isEmpty() )
208 rOutliner
.QuickDelete( rSel
);
212 rOutliner
.QuickInsertText( rText
, rSel
);
216 void SvxOutlinerForwarder::QuickInsertLineBreak( const ESelection
& rSel
)
219 rOutliner
.QuickInsertLineBreak( rSel
);
222 void SvxOutlinerForwarder::QuickInsertField( const SvxFieldItem
& rFld
, const ESelection
& rSel
)
225 rOutliner
.QuickInsertField( rFld
, rSel
);
228 void SvxOutlinerForwarder::QuickSetAttribs( const SfxItemSet
& rSet
, const ESelection
& rSel
)
231 rOutliner
.QuickSetAttribs( rSet
, rSel
);
234 OUString
SvxOutlinerForwarder::CalcFieldValue( const SvxFieldItem
& rField
, sal_Int32 nPara
, sal_Int32 nPos
, std::optional
<Color
>& rpTxtColor
, std::optional
<Color
>& rpFldColor
, std::optional
<FontLineStyle
>& rpFldLineStyle
)
236 return rOutliner
.CalcFieldValue( rField
, nPara
, nPos
, rpTxtColor
, rpFldColor
, rpFldLineStyle
);
239 void SvxOutlinerForwarder::FieldClicked( const SvxFieldItem
& /*rField*/ )
243 bool SvxOutlinerForwarder::IsValid() const
245 // cannot reliably query outliner state
246 // while in the middle of an update
247 return rOutliner
.IsUpdateLayout();
250 SfxItemState
SvxOutlinerForwarder::GetItemState( const ESelection
& rSel
, sal_uInt16 nWhich
) const
252 return GetSvxEditEngineItemState( rOutliner
.GetEditEngine(), rSel
, nWhich
);
255 SfxItemState
SvxOutlinerForwarder::GetItemState( sal_Int32 nPara
, sal_uInt16 nWhich
) const
257 const SfxItemSet
& rSet
= rOutliner
.GetParaAttribs( nPara
);
258 return rSet
.GetItemState( nWhich
);
262 void SvxOutlinerForwarder::flushCache()
264 moAttribsCache
.reset();
265 moParaAttribsCache
.reset();
268 LanguageType
SvxOutlinerForwarder::GetLanguage( sal_Int32 nPara
, sal_Int32 nIndex
) const
270 return rOutliner
.GetLanguage(nPara
, nIndex
);
273 std::vector
<EFieldInfo
> SvxOutlinerForwarder::GetFieldInfo( sal_Int32 nPara
) const
275 return rOutliner
.GetEditEngine().GetFieldInfo( nPara
);
278 EBulletInfo
SvxOutlinerForwarder::GetBulletInfo( sal_Int32 nPara
) const
280 return rOutliner
.GetBulletInfo( nPara
);
283 tools::Rectangle
SvxOutlinerForwarder::GetCharBounds( sal_Int32 nPara
, sal_Int32 nIndex
) const
285 // EditEngine's 'internal' methods like GetCharacterBounds()
286 // don't rotate for vertical text.
287 Size
aSize( rOutliner
.CalcTextSize() );
288 // swap width and height
289 tools::Long tmp
= aSize
.Width();
290 aSize
.setWidth(aSize
.Height());
291 aSize
.setHeight(tmp
);
292 bool bIsVertical( rOutliner
.IsVertical() );
294 // #108900# Handle virtual position one-past-the end of the string
295 if( nIndex
>= GetTextLen(nPara
) )
297 tools::Rectangle aLast
;
301 // use last character, if possible
302 aLast
= rOutliner
.GetEditEngine().GetCharacterBounds(EPaM(nPara
, nIndex
- 1));
304 // move at end of this last character, make one pixel wide
305 aLast
.Move( aLast
.Right() - aLast
.Left(), 0 );
306 aLast
.SetSize( Size(1, aLast
.GetHeight()) );
309 aLast
= SvxEditSourceHelper::EEToUserSpace( aLast
, aSize
, bIsVertical
);
313 // #109864# Bounds must lie within the paragraph
314 aLast
= GetParaBounds( nPara
);
316 // #109151# Don't use paragraph height, but line height
317 // instead. aLast is already CTL-correct
319 aLast
.SetSize( Size( rOutliner
.GetLineHeight(nPara
), 1 ) );
321 aLast
.SetSize( Size( 1, rOutliner
.GetLineHeight(nPara
) ) );
328 return SvxEditSourceHelper::EEToUserSpace( rOutliner
.GetEditEngine().GetCharacterBounds( EPaM(nPara
, nIndex
) ),
329 aSize
, bIsVertical
);
333 tools::Rectangle
SvxOutlinerForwarder::GetParaBounds( sal_Int32 nPara
) const
335 return rOutliner
.GetParaBounds( nPara
);
338 MapMode
SvxOutlinerForwarder::GetMapMode() const
340 return rOutliner
.GetRefMapMode();
343 OutputDevice
* SvxOutlinerForwarder::GetRefDevice() const
345 return rOutliner
.GetRefDevice();
348 bool SvxOutlinerForwarder::GetIndexAtPoint( const Point
& rPos
, sal_Int32
& nPara
, sal_Int32
& nIndex
) const
350 Size
aSize( rOutliner
.CalcTextSize() );
351 // swap width and height
352 tools::Long tmp
= aSize
.Width();
353 aSize
.setWidth(aSize
.Height());
354 aSize
.setHeight(tmp
);
355 Point
aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos
,
357 rOutliner
.IsVertical() ));
359 EPaM aDocPos
= rOutliner
.GetEditEngine().FindDocPosition(aEEPos
);
361 nPara
= aDocPos
.nPara
;
362 nIndex
= aDocPos
.nIndex
;
367 bool SvxOutlinerForwarder::GetWordIndices( sal_Int32 nPara
, sal_Int32 nIndex
, sal_Int32
& nStart
, sal_Int32
& nEnd
) const
369 ESelection aRes
= rOutliner
.GetEditEngine().GetWord( ESelection(nPara
, nIndex
), css::i18n::WordType::DICTIONARY_WORD
);
371 if( aRes
.start
.nPara
== nPara
&&
372 aRes
.start
.nPara
== aRes
.end
.nPara
)
374 nStart
= aRes
.start
.nIndex
;
375 nEnd
= aRes
.end
.nIndex
;
383 bool SvxOutlinerForwarder::GetAttributeRun( sal_Int32
& nStartIndex
, sal_Int32
& nEndIndex
, sal_Int32 nPara
, sal_Int32 nIndex
, bool bInCell
) const
385 SvxEditSourceHelper::GetAttributeRun( nStartIndex
, nEndIndex
, rOutliner
.GetEditEngine(), nPara
, nIndex
, bInCell
);
389 sal_Int32
SvxOutlinerForwarder::GetLineCount( sal_Int32 nPara
) const
391 return rOutliner
.GetLineCount(nPara
);
394 sal_Int32
SvxOutlinerForwarder::GetLineLen( sal_Int32 nPara
, sal_Int32 nLine
) const
396 return rOutliner
.GetLineLen(nPara
, nLine
);
399 void SvxOutlinerForwarder::GetLineBoundaries( /*out*/sal_Int32
&rStart
, /*out*/sal_Int32
&rEnd
, sal_Int32 nPara
, sal_Int32 nLine
) const
401 return rOutliner
.GetEditEngine().GetLineBoundaries( rStart
, rEnd
, nPara
, nLine
);
404 sal_Int32
SvxOutlinerForwarder::GetLineNumberAtIndex( sal_Int32 nPara
, sal_Int32 nIndex
) const
406 return rOutliner
.GetEditEngine().GetLineNumberAtIndex( nPara
, nIndex
);
409 bool SvxOutlinerForwarder::QuickFormatDoc( bool )
411 rOutliner
.QuickFormatDoc();
416 bool SvxOutlinerForwarder::Delete( const ESelection
& rSelection
)
419 rOutliner
.QuickDelete( rSelection
);
420 rOutliner
.QuickFormatDoc();
425 bool SvxOutlinerForwarder::InsertText( const OUString
& rStr
, const ESelection
& rSelection
)
428 rOutliner
.QuickInsertText( rStr
, rSelection
);
429 rOutliner
.QuickFormatDoc();
434 bool SvxOutlinerForwarder::SupportsOutlineDepth() const
439 sal_Int16
SvxOutlinerForwarder::GetDepth( sal_Int32 nPara
) const
441 DBG_ASSERT( 0 <= nPara
&& nPara
< GetParagraphCount(), "SvxOutlinerForwarder::GetDepth: Invalid paragraph index");
443 Paragraph
* pPara
= rOutliner
.GetParagraph( nPara
);
445 sal_Int16 nLevel
= -1;
448 nLevel
= rOutliner
.GetDepth( nPara
);
453 bool SvxOutlinerForwarder::SetDepth( sal_Int32 nPara
, sal_Int16 nNewDepth
)
455 DBG_ASSERT( 0 <= nPara
&& nPara
< GetParagraphCount(), "SvxOutlinerForwarder::SetDepth: Invalid paragraph index");
457 if( (nNewDepth
>= -1) && (nNewDepth
<= 9) && (0 <= nPara
&& nPara
< GetParagraphCount()) )
459 Paragraph
* pPara
= rOutliner
.GetParagraph( nPara
);
462 rOutliner
.SetDepth( pPara
, nNewDepth
);
464 // const bool bOutlinerText = pSdrObject && (pSdrObject->GetObjInventor() == SdrInventor::Default) && (pSdrObject->GetObjIdentifier() == OBJ_OUTLINETEXT);
466 rOutliner
.SetLevelDependentStyleSheet( nPara
);
475 sal_Int32
SvxOutlinerForwarder::GetNumberingStartValue( sal_Int32 nPara
)
477 if( 0 <= nPara
&& nPara
< GetParagraphCount() )
479 return rOutliner
.GetNumberingStartValue( nPara
);
483 OSL_FAIL( "SvxOutlinerForwarder::GetNumberingStartValue)(), Invalid paragraph index");
488 void SvxOutlinerForwarder::SetNumberingStartValue( sal_Int32 nPara
, sal_Int32 nNumberingStartValue
)
490 if( 0 <= nPara
&& nPara
< GetParagraphCount() )
492 rOutliner
.SetNumberingStartValue( nPara
, nNumberingStartValue
);
496 OSL_FAIL( "SvxOutlinerForwarder::SetNumberingStartValue)(), Invalid paragraph index");
500 bool SvxOutlinerForwarder::IsParaIsNumberingRestart( sal_Int32 nPara
)
502 if( 0 <= nPara
&& nPara
< GetParagraphCount() )
504 return rOutliner
.IsParaIsNumberingRestart( nPara
);
508 OSL_FAIL( "SvxOutlinerForwarder::IsParaIsNumberingRestart)(), Invalid paragraph index");
513 void SvxOutlinerForwarder::SetParaIsNumberingRestart( sal_Int32 nPara
, bool bParaIsNumberingRestart
)
515 if( 0 <= nPara
&& nPara
< GetParagraphCount() )
517 rOutliner
.SetParaIsNumberingRestart( nPara
, bParaIsNumberingRestart
);
521 OSL_FAIL( "SvxOutlinerForwarder::SetParaIsNumberingRestart)(), Invalid paragraph index");
525 const SfxItemSet
* SvxOutlinerForwarder::GetEmptyItemSetPtr()
527 EditEngine
& rEditEngine
= const_cast< EditEngine
& >( rOutliner
.GetEditEngine() );
528 return &rEditEngine
.GetEmptyItemSet();
531 void SvxOutlinerForwarder::AppendParagraph()
533 EditEngine
& rEditEngine
= const_cast< EditEngine
& >( rOutliner
.GetEditEngine() );
534 rEditEngine
.InsertParagraph( rEditEngine
.GetParagraphCount(), OUString() );
537 sal_Int32
SvxOutlinerForwarder::AppendTextPortion( sal_Int32 nPara
, const OUString
&rText
, const SfxItemSet
& /*rSet*/ )
541 EditEngine
& rEditEngine
= const_cast< EditEngine
& >( rOutliner
.GetEditEngine() );
542 sal_Int32 nParaCount
= rEditEngine
.GetParagraphCount();
543 DBG_ASSERT( 0 <= nPara
&& nPara
< nParaCount
, "paragraph index out of bounds" );
544 if (0 <= nPara
&& nPara
< nParaCount
)
546 nLen
= rEditEngine
.GetTextLen( nPara
);
547 rEditEngine
.QuickInsertText(rText
, ESelection(nPara
, nLen
));
553 void SvxOutlinerForwarder::CopyText(const SvxTextForwarder
& rSource
)
555 const SvxOutlinerForwarder
* pSourceForwarder
= dynamic_cast< const SvxOutlinerForwarder
* >( &rSource
);
556 if( !pSourceForwarder
)
558 std::optional
<OutlinerParaObject
> pNewOutlinerParaObject
= pSourceForwarder
->rOutliner
.CreateParaObject();
559 rOutliner
.SetText( *pNewOutlinerParaObject
);
563 sal_Int32
SvxTextForwarder::GetNumberingStartValue( sal_Int32
)
568 void SvxTextForwarder::SetNumberingStartValue( sal_Int32
, sal_Int32
)
572 bool SvxTextForwarder::IsParaIsNumberingRestart( sal_Int32
)
577 void SvxTextForwarder::SetParaIsNumberingRestart( sal_Int32
, bool )
582 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */