xref: /core/sw/source/uibase/shells/txtattr.cxx (revision a01a5bd9)
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #include <hintids.hxx>
21 
22 #include <svl/whiter.hxx>
23 #include <svl/stritem.hxx>
24 #include <svl/ctloptions.hxx>
25 #include <swmodule.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/request.hxx>
28 #include <sfx2/viewfrm.hxx>
29 #include <editeng/fhgtitem.hxx>
30 #include <editeng/adjustitem.hxx>
31 #include <editeng/lspcitem.hxx>
32 #include <editeng/lrspitem.hxx>
33 #include <editeng/udlnitem.hxx>
34 #include <editeng/escapementitem.hxx>
35 #include <sfx2/htmlmode.hxx>
36 #include <editeng/scripttypeitem.hxx>
37 #include <editeng/frmdiritem.hxx>
38 #include <editeng/cmapitem.hxx>
39 #include <paratr.hxx>
40 
41 #include <fmtinfmt.hxx>
42 #include <wrtsh.hxx>
43 #include <view.hxx>
44 #include <viewopt.hxx>
45 #include <uitool.hxx>
46 #include <textsh.hxx>
47 #include <swundo.hxx>
48 #include <fmtcol.hxx>
49 
50 #include <cmdid.h>
51 #include <globals.h>
52 #include <SwStyleNameMapper.hxx>
53 #include <swabstdlg.hxx>
54 #include <memory>
55 
56 const sal_uInt32 nFontInc = 40;      // 2pt
57 const sal_uInt32 nFontMaxSz = 19998; // 999.9pt
58 
59 void SwTextShell::ExecCharAttr(SfxRequest &rReq)
60 {
61     SwWrtShell &rSh = GetShell();
62     const SfxItemSet  *pArgs   = rReq.GetArgs();
63     int        eState = STATE_TOGGLE;
64     sal_uInt16 nWhich = rReq.GetSlot();
65 
66     if(pArgs )
67     {
68         const SfxPoolItem* pItem;
69         pArgs->GetItemState(nWhich, false, &pItem);
70         eState =  static_cast<const SfxBoolItem &>( pArgs->
71                                 Get( nWhich )).GetValue() ? STATE_ON : STATE_OFF;
72     }
73 
74     SfxItemSet aSet( GetPool(), svl::Items<RES_CHRATR_BEGIN, RES_CHRATR_END-1>{} );
75     if (STATE_TOGGLE == eState)
76         rSh.GetCurAttr( aSet );
77 
78     switch ( nWhich )
79     {
80         case FN_SET_SUB_SCRIPT:
81         case FN_SET_SUPER_SCRIPT:
82         {
83             SvxEscapement eEscape = SvxEscapement::Subscript;
84             switch (eState)
85             {
86             case STATE_TOGGLE:
87             {
88                 short nTmpEsc = aSet.Get( RES_CHRATR_ESCAPEMENT ).GetEsc();
89                 eEscape = nWhich == FN_SET_SUPER_SCRIPT ?
90                                 SvxEscapement::Superscript:
91                                 SvxEscapement::Subscript;
92                 if( (nWhich == FN_SET_SUB_SCRIPT && nTmpEsc < 0) ||
93                             (nWhich == FN_SET_SUPER_SCRIPT && nTmpEsc > 0) )
94                     eEscape = SvxEscapement::Off;
95 
96                 SfxBindings& rBind = GetView().GetViewFrame()->GetBindings();
97                 if( nWhich == FN_SET_SUB_SCRIPT )
98                     rBind.SetState( SfxBoolItem( FN_SET_SUPER_SCRIPT,
99                                                                     false ) );
100                 else
101                     rBind.SetState( SfxBoolItem( FN_SET_SUB_SCRIPT,
102                                                                     false ) );
103 
104             }
105             break;
106             case STATE_ON:
107                 eEscape = nWhich == FN_SET_SUPER_SCRIPT ?
108                                 SvxEscapement::Superscript:
109                                 SvxEscapement::Subscript;
110                 break;
111             case STATE_OFF:
112                 eEscape = SvxEscapement::Off;
113                 break;
114             }
115             SvxEscapementItem aEscape( eEscape, RES_CHRATR_ESCAPEMENT );
116             if(eEscape == SvxEscapement::Superscript)
117                 aEscape.GetEsc() = DFLT_ESC_AUTO_SUPER;
118             else if(eEscape == SvxEscapement::Subscript)
119                 aEscape.GetEsc() = DFLT_ESC_AUTO_SUB;
120             rSh.SetAttrItem( aEscape );
121             rReq.AppendItem( aEscape );
122             rReq.Done();
123         }
124         break;
125 
126         case FN_SET_SMALL_CAPS:
127         {
128             SvxCaseMap eCaseMap = SvxCaseMap::SmallCaps;
129             switch (eState)
130             {
131             case STATE_TOGGLE:
132             {
133                 SvxCaseMap eTmpCaseMap = aSet.Get(RES_CHRATR_CASEMAP).GetCaseMap();
134                 if (eTmpCaseMap == SvxCaseMap::SmallCaps)
135                     eCaseMap = SvxCaseMap::NotMapped;
136             }
137             break;
138             case STATE_ON:
139                 // Nothing to do, already set.
140                 break;
141             case STATE_OFF:
142                 eCaseMap = SvxCaseMap::NotMapped;
143                 break;
144             }
145             SvxCaseMapItem aCaseMap(eCaseMap, RES_CHRATR_CASEMAP);
146             rSh.SetAttrItem(aCaseMap);
147             rReq.AppendItem(aCaseMap);
148             rReq.Done();
149         }
150         break;
151 
152         case FN_UPDATE_STYLE_BY_EXAMPLE:
153             rSh.QuickUpdateStyle();
154             rReq.Done();
155             break;
156 
157         case SID_ULINE_VAL_NONE:
158         {
159             SvxUnderlineItem aUnderline(LINESTYLE_NONE, RES_CHRATR_UNDERLINE );
160             rSh.SetAttrItem( aUnderline );
161             rReq.AppendItem( aUnderline );
162             rReq.Done();
163             break;
164         }
165 
166         case SID_ULINE_VAL_SINGLE:
167         case SID_ULINE_VAL_DOUBLE:
168         case SID_ULINE_VAL_DOTTED:
169         {
170             FontLineStyle eOld = aSet.Get(RES_CHRATR_UNDERLINE).GetLineStyle();
171             FontLineStyle eNew = eOld;
172 
173             switch (nWhich)
174             {
175                 case SID_ULINE_VAL_SINGLE:
176                     eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
177                     break;
178                 case SID_ULINE_VAL_DOUBLE:
179                     eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
180                     break;
181                 case SID_ULINE_VAL_DOTTED:
182                     eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
183                     break;
184             }
185 
186             SvxUnderlineItem aUnderline(eNew, RES_CHRATR_UNDERLINE );
187             rSh.SetAttrItem( aUnderline );
188             rReq.AppendItem( aUnderline );
189             rReq.Done();
190         }
191         break;
192         case FN_REMOVE_DIRECT_CHAR_FORMATS:
193             if( !rSh.HasReadonlySel() && rSh.IsEndPara())
194                 rSh.DontExpandFormat();
195         break;
196         default:
197             OSL_FAIL("wrong  dispatcher");
198             return;
199     }
200 }
201 
202 void SwTextShell::ExecCharAttrArgs(SfxRequest &rReq)
203 {
204     sal_uInt16 nSlot = rReq.GetSlot();
205     const SfxItemSet* pArgs = rReq.GetArgs();
206     bool bArgs = pArgs != nullptr && pArgs->Count() > 0;
207     SwWrtShell& rWrtSh = GetShell();
208     SwTextFormatColl* pColl = nullptr;
209 
210     // Is only set if the whole paragraph is selected and AutoUpdateFormat is set.
211     if (rWrtSh.HasSelection() && rWrtSh.IsSelFullPara())
212     {
213         pColl = rWrtSh.GetCurTextFormatColl();
214         if ( pColl && !pColl->IsAutoUpdateFormat() )
215             pColl = nullptr;
216     }
217     SfxItemPool& rPool = GetPool();
218     sal_uInt16 nWhich = rPool.GetWhich( nSlot );
219     switch (nSlot)
220     {
221         case FN_TXTATR_INET:
222         // Special treatment of the PoolId of the SwFormatInetFormat
223         if(bArgs)
224         {
225             const SfxPoolItem& rItem = pArgs->Get( nWhich );
226 
227             SwFormatINetFormat aINetFormat( static_cast<const SwFormatINetFormat&>(rItem) );
228             if ( USHRT_MAX == aINetFormat.GetVisitedFormatId() )
229             {
230                 OSL_ENSURE( false, "<SwTextShell::ExecCharAttrArgs(..)> - unexpected visited character format ID at hyperlink attribute" );
231                 aINetFormat.SetVisitedFormatAndId(
232                         aINetFormat.GetVisitedFormat(),
233                         SwStyleNameMapper::GetPoolIdFromUIName( aINetFormat.GetVisitedFormat(), SwGetPoolIdFromName::ChrFmt ) );
234             }
235             if ( USHRT_MAX == aINetFormat.GetINetFormatId() )
236             {
237                 OSL_ENSURE( false, "<SwTextShell::ExecCharAttrArgs(..)> - unexpected unvisited character format ID at hyperlink attribute" );
238                 aINetFormat.SetINetFormatAndId(
239                         aINetFormat.GetINetFormat(),
240                         SwStyleNameMapper::GetPoolIdFromUIName( aINetFormat.GetINetFormat(), SwGetPoolIdFromName::ChrFmt ) );
241             }
242 
243             if ( pColl )
244                 pColl->SetFormatAttr( aINetFormat );
245             else
246                 rWrtSh.SetAttrItem( aINetFormat );
247             rReq.Done();
248         }
249         break;
250 
251         case FN_GROW_FONT_SIZE:
252         case FN_SHRINK_FONT_SIZE:
253         {
254             SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT, rPool );
255             rWrtSh.GetCurAttr( aSetItem.GetItemSet() );
256             SfxItemSet aAttrSet( rPool, aSetItem.GetItemSet().GetRanges() );
257 
258             SvtScriptType nScriptTypes = rWrtSh.GetScriptType();
259             const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
260                                         aSetItem.GetItemOfScript( nScriptTypes ) ) );
261             std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >> vItems;
262             // simple case where selected text has one size and
263             // (tdf#124919) selection is not multiple table cells
264             if (pSize && !rWrtSh.IsTableMode())
265             {
266                 // must create new one, otherwise document is without pam
267                 SwPaM* pPaM = rWrtSh.GetCursor();
268                 vItems.emplace_back( pSize, std::make_unique<SwPaM>( *(pPaM->GetMark()), *(pPaM->GetPoint())) );
269             }
270             else
271                 vItems = rWrtSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
272 
273             rWrtSh.StartUndo( SwUndoId::INSATTR );
274             for( std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >& iPair : vItems )
275             {
276                 std::unique_ptr<SwPaM> pPaM = std::move(iPair.second);
277                 const SfxPoolItem* pItem = iPair.first;
278                 aSetItem.GetItemSet().ClearItem();
279                 rWrtSh.GetPaMAttr( pPaM.get(), aSetItem.GetItemSet() );
280                 aAttrSet.SetRanges( aSetItem.GetItemSet().GetRanges() );
281 
282                 pSize = static_cast<const SvxFontHeightItem*>( pItem );
283                 if (pSize)
284                 {
285                     SvxFontHeightItem aSize(*pSize);
286 
287                     sal_uInt32 nSize = aSize.GetHeight();
288 
289                     if ( nSlot == FN_GROW_FONT_SIZE && ( nSize += nFontInc ) > nFontMaxSz )
290                         nSize = nFontMaxSz;
291                     else if ( nSlot == FN_SHRINK_FONT_SIZE && ( nSize -= nFontInc ) < nFontInc )
292                         nSize = nFontInc;
293 
294                     aSize.SetHeight( nSize );
295                     aSetItem.PutItemForScriptType( nScriptTypes, aSize );
296                     aAttrSet.Put( aSetItem.GetItemSet() );
297                     if( pColl )
298                         pColl->SetFormatAttr( aAttrSet );
299                     else
300                         rWrtSh.SetAttrSet( aAttrSet, SetAttrMode::DEFAULT, pPaM.get() );
301                 }
302             }
303             rWrtSh.EndUndo( SwUndoId::INSATTR );
304             rReq.Done();
305         }
306         break;
307 
308         default:
309             OSL_FAIL("wrong  dispatcher");
310             return;
311     }
312 }
313 
314 void SwTextShell::ExecParaAttr(SfxRequest &rReq)
315 {
316     SvxAdjust eAdjst;
317     sal_uInt16 ePropL;
318     const SfxItemSet* pArgs = rReq.GetArgs();
319 
320     // Get both attributes immediately isn't more expensive!!
321     SfxItemSet aSet( GetPool(),
322         svl::Items<RES_PARATR_LINESPACING, RES_PARATR_ADJUST,
323         RES_FRAMEDIR, RES_FRAMEDIR>{} );
324 
325     sal_uInt16 nSlot = rReq.GetSlot();
326     switch (nSlot)
327     {
328         case SID_ATTR_PARA_ADJUST:
329         {
330             if( pArgs && SfxItemState::SET == pArgs->GetItemState(RES_PARATR_ADJUST) )
331             {
332                 const SvxAdjustItem& rAdj = pArgs->Get(RES_PARATR_ADJUST);
333                 SvxAdjustItem aAdj( rAdj.GetAdjust(), RES_PARATR_ADJUST );
334                 if ( rAdj.GetAdjust() == SvxAdjust::Block )
335                 {
336                     aAdj.SetLastBlock( rAdj.GetLastBlock() );
337                     aAdj.SetOneWord( rAdj.GetOneWord() );
338                 }
339 
340                 aSet.Put(aAdj);
341             }
342         }
343         break;
344         case SID_ATTR_PARA_ADJUST_LEFT:     eAdjst =  SvxAdjust::Left;      goto SET_ADJUST;
345         case SID_ATTR_PARA_ADJUST_RIGHT:    eAdjst =  SvxAdjust::Right;     goto SET_ADJUST;
346         case SID_ATTR_PARA_ADJUST_CENTER:   eAdjst =  SvxAdjust::Center;    goto SET_ADJUST;
347         case SID_ATTR_PARA_ADJUST_BLOCK:    eAdjst =  SvxAdjust::Block;     goto SET_ADJUST;
348 SET_ADJUST:
349         {
350             aSet.Put(SvxAdjustItem(eAdjst,RES_PARATR_ADJUST));
351             rReq.AppendItem( SfxBoolItem( GetPool().GetWhich(nSlot), true ) );
352         }
353         break;
354 
355         case SID_ATTR_PARA_LINESPACE:
356             if(pArgs && SfxItemState::SET == pArgs->GetItemState( GetPool().GetWhich(nSlot) ))
357             {
358                 SvxLineSpacingItem aLineSpace = static_cast<const SvxLineSpacingItem&>( pArgs->Get(
359                                                             GetPool().GetWhich(nSlot)));
360                 aSet.Put( aLineSpace );
361             }
362         break;
363         case SID_ATTR_PARA_LINESPACE_10:    ePropL = 100;   goto SET_LINESPACE;
364         case SID_ATTR_PARA_LINESPACE_15:    ePropL = 150;   goto SET_LINESPACE;
365         case SID_ATTR_PARA_LINESPACE_20:    ePropL = 200;   goto SET_LINESPACE;
366 
367 SET_LINESPACE:
368         {
369 
370             SvxLineSpacingItem aLineSpacing(ePropL, RES_PARATR_LINESPACING );
371             aLineSpacing.SetLineSpaceRule( SvxLineSpaceRule::Auto );
372             if( 100 == ePropL )
373                 aLineSpacing.SetInterLineSpaceRule( SvxInterLineSpaceRule::Off );
374             else
375                 aLineSpacing.SetPropLineSpace(ePropL);
376             aSet.Put( aLineSpacing );
377         }
378         break;
379 
380         case SID_ATTR_PARA_LEFT_TO_RIGHT :
381         case SID_ATTR_PARA_RIGHT_TO_LEFT :
382         {
383             SfxItemSet aAdjustSet( GetPool(),
384                     svl::Items<RES_PARATR_ADJUST, RES_PARATR_ADJUST>{} );
385             GetShell().GetCurAttr(aAdjustSet);
386             bool bChgAdjust = false;
387             SfxItemState eAdjustState = aAdjustSet.GetItemState(RES_PARATR_ADJUST, false);
388             if(eAdjustState  >= SfxItemState::DEFAULT)
389             {
390                 SvxAdjust eAdjust =
391                         aAdjustSet.Get(RES_PARATR_ADJUST).GetAdjust();
392                 bChgAdjust = (SvxAdjust::Left  == eAdjust  &&  SID_ATTR_PARA_RIGHT_TO_LEFT == nSlot) ||
393                              (SvxAdjust::Right == eAdjust  &&  SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot);
394             }
395             else
396                 bChgAdjust = true;
397 
398             SvxFrameDirection eFrameDirection =
399                     (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot) ?
400                         SvxFrameDirection::Horizontal_LR_TB : SvxFrameDirection::Horizontal_RL_TB;
401             aSet.Put( SvxFrameDirectionItem( eFrameDirection, RES_FRAMEDIR ) );
402 
403             if (bChgAdjust)
404             {
405                 SvxAdjust eAdjust = (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot) ?
406                         SvxAdjust::Left : SvxAdjust::Right;
407                 SvxAdjustItem aAdjust( eAdjust, RES_PARATR_ADJUST );
408                 aSet.Put( aAdjust );
409                 aAdjust.SetWhich(SID_ATTR_PARA_ADJUST);
410                 GetView().GetViewFrame()->GetBindings().SetState( aAdjust );
411                 // Toggle numbering alignment
412                 const SwNumRule* pCurRule = GetShell().GetNumRuleAtCurrCursorPos();
413                 if( pCurRule )
414                 {
415                     SvxNumRule aRule = pCurRule->MakeSvxNumRule();
416 
417                     for(sal_uInt16 i = 0; i < aRule.GetLevelCount(); i++)
418                     {
419                         SvxNumberFormat aFormat(aRule.GetLevel(i));
420                         if(SvxAdjust::Left == aFormat.GetNumAdjust())
421                             aFormat.SetNumAdjust( SvxAdjust::Right );
422 
423                         else if(SvxAdjust::Right == aFormat.GetNumAdjust())
424                             aFormat.SetNumAdjust( SvxAdjust::Left );
425 
426                         aRule.SetLevel(i, aFormat, aRule.Get(i) != nullptr);
427                     }
428                     SwNumRule aSetRule( pCurRule->GetName(),
429                                         pCurRule->Get( 0 ).GetPositionAndSpaceMode() );
430                     aSetRule.SetSvxRule( aRule, GetShell().GetDoc());
431                     aSetRule.SetAutoRule( true );
432                     // no start or continuation of a list - list style is only changed
433                     GetShell().SetCurNumRule( aSetRule, false );
434                 }
435             }
436         }
437         break;
438 
439         default:
440             OSL_FAIL("wrong  dispatcher");
441             return;
442     }
443     SwWrtShell& rWrtSh = GetShell();
444     SwTextFormatColl* pColl = rWrtSh.GetCurTextFormatColl();
445     if(pColl && pColl->IsAutoUpdateFormat())
446     {
447         rWrtSh.AutoUpdatePara(pColl, aSet);
448     }
449     else
450         rWrtSh.SetAttrSet( aSet, SetAttrMode::DEFAULT, nullptr, true);
451     rReq.Done();
452 }
453 
454 void SwTextShell::ExecParaAttrArgs(SfxRequest &rReq)
455 {
456     SwWrtShell &rSh = GetShell();
457     const SfxItemSet *pArgs = rReq.GetArgs();
458     const SfxPoolItem *pItem = nullptr;
459 
460     sal_uInt16 nSlot = rReq.GetSlot();
461     if(pArgs)
462         pArgs->GetItemState(GetPool().GetWhich(nSlot), false, &pItem);
463     switch ( nSlot )
464     {
465         case FN_DROP_CHAR_STYLE_NAME:
466             if( pItem )
467             {
468                 OUString sCharStyleName = static_cast<const SfxStringItem*>(pItem)->GetValue();
469                 SfxItemSet aSet(GetPool(), svl::Items<RES_PARATR_DROP, RES_PARATR_DROP>{});
470                 rSh.GetCurAttr(aSet);
471                 SwFormatDrop aDropItem(aSet.Get(RES_PARATR_DROP));
472                 SwCharFormat* pFormat = nullptr;
473                 if(!sCharStyleName.isEmpty())
474                     pFormat = rSh.FindCharFormatByName( sCharStyleName );
475                 aDropItem.SetCharFormat( pFormat );
476                 aSet.Put(aDropItem);
477                 rSh.SetAttrSet(aSet);
478             }
479         break;
480         case FN_FORMAT_DROPCAPS:
481         {
482             if(pItem)
483             {
484                 rSh.SetAttrItem(*pItem);
485                 rReq.Done();
486             }
487             else
488             {
489                 SfxItemSet aSet(GetPool(), svl::Items<RES_PARATR_DROP, RES_PARATR_DROP,
490                                            HINT_END, HINT_END>{});
491                 rSh.GetCurAttr(aSet);
492                 SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create();
493                 ScopedVclPtr<SfxAbstractDialog> pDlg(pFact->CreateSwDropCapsDialog(GetView().GetFrameWeld(), aSet));
494                 if (pDlg->Execute() == RET_OK)
495                 {
496                     rSh.StartAction();
497                     rSh.StartUndo( SwUndoId::START );
498                     if ( SfxItemState::SET == aSet.GetItemState(HINT_END,false,&pItem) )
499                     {
500                         if ( !static_cast<const SfxStringItem*>(pItem)->GetValue().isEmpty() )
501                             rSh.ReplaceDropText(static_cast<const SfxStringItem*>(pItem)->GetValue());
502                     }
503                     rSh.SetAttrSet(*pDlg->GetOutputItemSet());
504                     rSh.EndUndo( SwUndoId::END );
505                     rSh.EndAction();
506                     rReq.Done(*pDlg->GetOutputItemSet());
507                 }
508             }
509         }
510          break;
511         case SID_ATTR_PARA_PAGEBREAK:
512             if(pItem)
513             {
514                 rSh.SetAttrItem( *pItem );
515                 rReq.Done();
516             }
517         break;
518         case SID_ATTR_PARA_MODEL:
519         {
520             if(pItem)
521             {
522                 SfxItemSet aCoreSet( GetPool(),
523                     svl::Items<RES_PAGEDESC,   RES_PAGEDESC,
524                     SID_ATTR_PARA_MODEL, SID_ATTR_PARA_MODEL>{});
525                 aCoreSet.Put(*pItem);
526                 SfxToSwPageDescAttr( rSh, aCoreSet);
527                 rSh.SetAttrSet(aCoreSet);
528                 rReq.Done();
529             }
530         }
531         break;
532 
533         default:
534             OSL_FAIL("wrong  dispatcher");
535             return;
536     }
537 }
538 
539 void SwTextShell::GetAttrState(SfxItemSet &rSet)
540 {
541     SwWrtShell &rSh = GetShell();
542     SfxItemPool& rPool = GetPool();
543     SfxItemSet aCoreSet(rPool, aTextFormatCollSetRange);
544     // Request *all* text attributes from the core.
545     // fdo#78737: this is called from SvxRuler, which requires the list indents!
546     rSh.GetCurAttr(aCoreSet, /* bMergeIndentValuesOfNumRule = */ true);
547 
548     SfxWhichIter aIter(rSet);
549     sal_uInt16 nSlot = aIter.FirstWhich();
550     bool bFlag = false;
551     SfxBoolItem aFlagItem;
552     const SfxPoolItem* pItem = nullptr;
553     SvxAdjust eAdjust = SvxAdjust::Left;
554     bool bAdjustGood = false;
555     SfxItemState eState = aCoreSet.GetItemState(RES_PARATR_ADJUST, false, &pItem);
556 
557     if( SfxItemState::DEFAULT == eState )
558         pItem = &rPool.GetDefaultItem(RES_PARATR_ADJUST);
559     if( SfxItemState::DEFAULT <= eState )
560     {
561         eAdjust = static_cast<const SvxAdjustItem* >( pItem)->GetAdjust();
562         bAdjustGood = true;
563     }
564 
565     short nEsc = 0;
566     eState =  aCoreSet.GetItemState(RES_CHRATR_ESCAPEMENT, false, &pItem);
567     if( SfxItemState::DEFAULT == eState )
568         pItem = &rPool.GetDefaultItem(RES_CHRATR_ESCAPEMENT);
569     if( eState >= SfxItemState::DEFAULT )
570         nEsc = static_cast<const SvxEscapementItem* >(pItem)->GetEsc();
571 
572     sal_uInt16 nLineSpace = 0;
573     eState =  aCoreSet.GetItemState(RES_PARATR_LINESPACING, false, &pItem);
574     if( SfxItemState::DEFAULT == eState )
575         pItem = &rPool.GetDefaultItem(RES_PARATR_LINESPACING);
576     if( SfxItemState::DEFAULT <= eState &&
577             static_cast<const SvxLineSpacingItem* >(pItem)->GetLineSpaceRule() == SvxLineSpaceRule::Auto )
578     {
579         if(SvxInterLineSpaceRule::Off ==
580                     static_cast<const SvxLineSpacingItem* >(pItem)->GetInterLineSpaceRule())
581             nLineSpace = 100;
582         else
583             nLineSpace = static_cast<const SvxLineSpacingItem* >(pItem)->GetPropLineSpace();
584     }
585 
586     SvxCaseMap eCaseMap = SvxCaseMap::NotMapped;
587     eState = aCoreSet.GetItemState(RES_CHRATR_CASEMAP, false, &pItem);
588     if (eState == SfxItemState::DEFAULT)
589         pItem = &rPool.GetDefaultItem(RES_CHRATR_CASEMAP);
590     if (eState >= SfxItemState::DEFAULT)
591         eCaseMap = static_cast<const SvxCaseMapItem*>(pItem)->GetCaseMap();
592 
593     while (nSlot)
594     {
595         switch(nSlot)
596         {
597             case FN_SET_SUPER_SCRIPT:
598                     bFlag = 0 < nEsc;
599                 break;
600             case FN_SET_SUB_SCRIPT:
601                     bFlag = 0 > nEsc;
602                 break;
603             case FN_SET_SMALL_CAPS:
604                 bFlag = eCaseMap == SvxCaseMap::SmallCaps;
605                 break;
606             case SID_ATTR_PARA_ADJUST_LEFT:
607                 if (!bAdjustGood)
608                 {
609                     rSet.InvalidateItem( nSlot );
610                     nSlot = 0;
611                 }
612                 else
613                     bFlag = SvxAdjust::Left == eAdjust;
614                 break;
615             case SID_ATTR_PARA_ADJUST_RIGHT:
616                 if (!bAdjustGood)
617                 {
618                     rSet.InvalidateItem( nSlot );
619                     nSlot = 0;
620                 }
621                 else
622                     bFlag = SvxAdjust::Right == eAdjust;
623                 break;
624             case SID_ATTR_PARA_ADJUST_CENTER:
625                 if (!bAdjustGood)
626                 {
627                     rSet.InvalidateItem( nSlot );
628                     nSlot = 0;
629                 }
630                 else
631                     bFlag = SvxAdjust::Center == eAdjust;
632                 break;
633             case SID_ATTR_PARA_ADJUST_BLOCK:
634             {
635                 if (!bAdjustGood)
636                 {
637                     rSet.InvalidateItem( nSlot );
638                     nSlot = 0;
639                 }
640                 else
641                 {
642                     bFlag = SvxAdjust::Block == eAdjust;
643                     sal_uInt16 nHtmlMode = GetHtmlMode(rSh.GetView().GetDocShell());
644                     if((nHtmlMode & HTMLMODE_ON) && !(nHtmlMode & HTMLMODE_FULL_STYLES ))
645                     {
646                         rSet.DisableItem( nSlot );
647                         nSlot = 0;
648                     }
649                 }
650             }
651             break;
652             case SID_ATTR_PARA_LINESPACE_10:
653                 bFlag = nLineSpace == 100;
654             break;
655             case SID_ATTR_PARA_LINESPACE_15:
656                 bFlag = nLineSpace == 150;
657             break;
658             case SID_ATTR_PARA_LINESPACE_20:
659                 bFlag = nLineSpace == 200;
660             break;
661             case FN_GROW_FONT_SIZE:
662             case FN_SHRINK_FONT_SIZE:
663             {
664                 SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONTHEIGHT,
665                                             *rSet.GetPool() );
666                 aSetItem.GetItemSet().Put( aCoreSet, false );
667                 const SvxFontHeightItem* pSize( static_cast<const SvxFontHeightItem*>(
668                                             aSetItem.GetItemOfScript( rSh.GetScriptType() ) ) );
669 
670                 if( pSize ) // selection is of one size
671                 {
672                     sal_uInt32 nSize = pSize->GetHeight();
673                     if( nSize == nFontMaxSz )
674                         rSet.DisableItem( FN_GROW_FONT_SIZE );
675                     else if( nSize == nFontInc )
676                         rSet.DisableItem( FN_SHRINK_FONT_SIZE );
677                 }
678                 else
679                 {
680                     std::vector<std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM> >>
681                         vFontHeight = rSh.GetItemWithPaM( RES_CHRATR_FONTSIZE );
682                     for ( const std::pair< const SfxPoolItem*, std::unique_ptr<SwPaM>>& aIt : vFontHeight )
683                     {
684                         if (!aIt.first)
685                         {
686                             rSet.DisableItem(FN_GROW_FONT_SIZE);
687                             rSet.DisableItem(FN_SHRINK_FONT_SIZE);
688                             break;
689                         }
690                         pSize = static_cast<const SvxFontHeightItem*>( aIt.first );
691                         sal_uInt32 nSize = pSize->GetHeight();
692                         if( nSize == nFontMaxSz )
693                             rSet.DisableItem( FN_GROW_FONT_SIZE );
694                         else if( nSize == nFontInc )
695                             rSet.DisableItem( FN_SHRINK_FONT_SIZE );
696                     }
697                 }
698                 nSlot = 0;
699             }
700             break;
701             case SID_ULINE_VAL_NONE:
702             case SID_ULINE_VAL_SINGLE:
703             case SID_ULINE_VAL_DOUBLE:
704             case SID_ULINE_VAL_DOTTED:
705             {
706                 eState = aCoreSet.GetItemState(RES_CHRATR_UNDERLINE);
707                 if( eState >= SfxItemState::DEFAULT )
708                 {
709                     FontLineStyle eLineStyle = aCoreSet.Get(RES_CHRATR_UNDERLINE).GetLineStyle();
710 
711                     switch (nSlot)
712                     {
713                         case SID_ULINE_VAL_NONE:
714                             rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_NONE));
715                             break;
716                         case SID_ULINE_VAL_SINGLE:
717                             rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_SINGLE));
718                             break;
719                         case SID_ULINE_VAL_DOUBLE:
720                             rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_DOUBLE));
721                             break;
722                         case SID_ULINE_VAL_DOTTED:
723                             rSet.Put(SfxBoolItem(nSlot, eLineStyle == LINESTYLE_DOTTED));
724                             break;
725                     }
726                 }
727                 else
728                     rSet.InvalidateItem(nSlot);
729                 nSlot = 0;
730             }
731             break;
732             case SID_ATTR_PARA_ADJUST:
733                 if (!bAdjustGood)
734                     rSet.InvalidateItem( nSlot );
735                 else
736                     rSet.Put(SvxAdjustItem(eAdjust, SID_ATTR_PARA_ADJUST ));
737                 nSlot = 0;
738             break;
739             case SID_ATTR_PARA_LRSPACE:
740             case SID_ATTR_PARA_LEFTSPACE:
741             case SID_ATTR_PARA_RIGHTSPACE:
742             case SID_ATTR_PARA_FIRSTLINESPACE:
743             {
744                 eState = aCoreSet.GetItemState(RES_LR_SPACE);
745                 if( eState >= SfxItemState::DEFAULT )
746                 {
747                     SvxLRSpaceItem aLR = aCoreSet.Get( RES_LR_SPACE );
748                     aLR.SetWhich(nSlot);
749                     rSet.Put(aLR);
750                 }
751                 else
752                     rSet.InvalidateItem(nSlot);
753                 nSlot = 0;
754             }
755             break;
756 
757             case SID_ATTR_PARA_LEFT_TO_RIGHT :
758             case SID_ATTR_PARA_RIGHT_TO_LEFT :
759             {
760                 if ( !SW_MOD()->GetCTLOptions().IsCTLFontEnabled() )
761                 {
762                     rSet.DisableItem( nSlot );
763                     nSlot = 0;
764                 }
765                 else
766                 {
767                     // is the item set?
768                     sal_uInt16 nHtmlMode = GetHtmlMode(rSh.GetView().GetDocShell());
769                     if((!(nHtmlMode & HTMLMODE_ON) || (0 != (nHtmlMode & HTMLMODE_SOME_STYLES))) &&
770                     aCoreSet.GetItemState( RES_FRAMEDIR, false ) >= SfxItemState::DEFAULT)
771                     {
772                         SvxFrameDirection eFrameDir =
773                                 aCoreSet.Get(RES_FRAMEDIR).GetValue();
774                         if (SvxFrameDirection::Environment == eFrameDir)
775                         {
776                             eFrameDir = rSh.IsInRightToLeftText() ?
777                                     SvxFrameDirection::Horizontal_RL_TB : SvxFrameDirection::Horizontal_LR_TB;
778                         }
779                         bFlag = (SID_ATTR_PARA_LEFT_TO_RIGHT == nSlot &&
780                                             SvxFrameDirection::Horizontal_LR_TB == eFrameDir) ||
781                                 (SID_ATTR_PARA_RIGHT_TO_LEFT == nSlot &&
782                                             SvxFrameDirection::Horizontal_RL_TB == eFrameDir);
783                     }
784                     else
785                     {
786                         rSet.InvalidateItem(nSlot);
787                         nSlot = 0;
788                     }
789                 }
790             }
791             break;
792 
793             case SID_ATTR_CHAR_LANGUAGE:
794             case SID_ATTR_CHAR_KERNING:
795             case RES_PARATR_DROP:
796             {
797 #if OSL_DEBUG_LEVEL > 1
798                 const SfxPoolItem& rItem = aCoreSet.Get(GetPool().GetWhich(nSlot), true);
799                 rSet.Put(rItem);
800 #else
801                 rSet.Put(aCoreSet.Get( GetPool().GetWhich(nSlot)));
802 #endif
803                 nSlot = 0;
804             }
805             break;
806             case SID_ATTR_PARA_MODEL:
807             {
808                 SfxItemSet aTemp(GetPool(),
809                         svl::Items<RES_PAGEDESC,RES_PAGEDESC,
810                         SID_ATTR_PARA_MODEL,SID_ATTR_PARA_MODEL>{});
811                 aTemp.Put(aCoreSet);
812                 ::SwToSfxPageDescAttr(aTemp);
813                 rSet.Put(aTemp.Get(SID_ATTR_PARA_MODEL));
814                 nSlot = 0;
815             }
816             break;
817             case RES_TXTATR_INETFMT:
818             {
819                 SfxItemSet aSet(GetPool(), svl::Items<RES_TXTATR_INETFMT, RES_TXTATR_INETFMT>{});
820                 rSh.GetCurAttr(aSet);
821                 const SfxPoolItem& rItem = aSet.Get(RES_TXTATR_INETFMT);
822                 rSet.Put(rItem);
823                 nSlot = 0;
824             }
825             break;
826 
827             default:
828             // Do nothing
829             nSlot = 0;
830             break;
831 
832         }
833         if( nSlot )
834         {
835             aFlagItem.SetWhich( nSlot );
836             aFlagItem.SetValue( bFlag );
837             rSet.Put( aFlagItem );
838         }
839         nSlot = aIter.NextWhich();
840     }
841 
842     rSet.Put(aCoreSet,false);
843 }
844 
845 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
846