xref: /core/editeng/source/items/frmitems.cxx (revision e12fa18c)
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 <memory>
21 #include <com/sun/star/uno/Any.hxx>
22 #include <com/sun/star/drawing/LineStyle.hpp>
23 #include <com/sun/star/script/Converter.hpp>
24 #include <com/sun/star/table/ShadowLocation.hpp>
25 #include <com/sun/star/table/ShadowFormat.hpp>
26 #include <com/sun/star/table/BorderLine2.hpp>
27 #include <com/sun/star/table/BorderLineStyle.hpp>
28 #include <com/sun/star/style/BreakType.hpp>
29 #include <com/sun/star/style/GraphicLocation.hpp>
30 #include <com/sun/star/awt/Size.hpp>
31 #include <com/sun/star/text/WritingMode2.hpp>
32 #include <com/sun/star/frame/status/UpperLowerMarginScale.hpp>
33 #include <com/sun/star/frame/status/LeftRightMarginScale.hpp>
34 #include <com/sun/star/drawing/ShadingPattern.hpp>
35 #include <com/sun/star/graphic/XGraphic.hpp>
36 
37 #include <osl/diagnose.h>
38 #include <sal/log.hxx>
39 #include <i18nutil/unicode.hxx>
40 #include <unotools/ucbstreamhelper.hxx>
41 #include <comphelper/processfactory.hxx>
42 #include <vcl/GraphicObject.hxx>
43 #include <tools/urlobj.hxx>
44 #include <svl/memberid.h>
45 #include <rtl/math.hxx>
46 #include <rtl/ustring.hxx>
47 #include <tools/mapunit.hxx>
48 #include <vcl/graphicfilter.hxx>
49 #include <vcl/settings.hxx>
50 #include <vcl/svapp.hxx>
51 #include <editeng/editrids.hrc>
52 #include <editeng/pbinitem.hxx>
53 #include <editeng/sizeitem.hxx>
54 #include <editeng/lrspitem.hxx>
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/prntitem.hxx>
57 #include <editeng/opaqitem.hxx>
58 #include <editeng/protitem.hxx>
59 #include <editeng/shaditem.hxx>
60 #include <editeng/borderline.hxx>
61 #include <editeng/boxitem.hxx>
62 #include <editeng/formatbreakitem.hxx>
63 #include <editeng/keepitem.hxx>
64 #include <editeng/lineitem.hxx>
65 #include <editeng/brushitem.hxx>
66 #include <editeng/frmdiritem.hxx>
67 #include <editeng/itemtype.hxx>
68 #include <editeng/eerdll.hxx>
69 #include <editeng/memberids.h>
70 #include <libxml/xmlwriter.h>
71 #include <o3tl/enumrange.hxx>
72 #include <o3tl/safeint.hxx>
73 #include <vcl/GraphicLoader.hxx>
74 
75 #include <boost/property_tree/ptree.hpp>
76 
77 using namespace ::editeng;
78 using namespace ::com::sun::star;
79 using namespace ::com::sun::star::drawing;
80 using namespace ::com::sun::star::table::BorderLineStyle;
81 
82 
83 SfxPoolItem* SvxPaperBinItem::CreateDefault() { return new  SvxPaperBinItem(0);}
84 SfxPoolItem* SvxSizeItem::CreateDefault() { return new  SvxSizeItem(0);}
85 SfxPoolItem* SvxLRSpaceItem::CreateDefault() { return new  SvxLRSpaceItem(0);}
86 SfxPoolItem* SvxULSpaceItem::CreateDefault() { return new  SvxULSpaceItem(0);}
87 SfxPoolItem* SvxProtectItem::CreateDefault() { return new  SvxProtectItem(0);}
88 SfxPoolItem* SvxBrushItem::CreateDefault() { return new  SvxBrushItem(0);}
89 SfxPoolItem* SvxShadowItem::CreateDefault() { return new  SvxShadowItem(0);}
90 SfxPoolItem* SvxBoxItem::CreateDefault() { return new  SvxBoxItem(0);}
91 SfxPoolItem* SvxBoxInfoItem::CreateDefault() { return new  SvxBoxInfoItem(0);}
92 SfxPoolItem* SvxFormatBreakItem::CreateDefault() { return new  SvxFormatBreakItem(SvxBreak::NONE, 0);}
93 SfxPoolItem* SvxFormatKeepItem::CreateDefault() { return new  SvxFormatKeepItem(false, 0);}
94 SfxPoolItem* SvxLineItem::CreateDefault() { return new  SvxLineItem(0);}
95 
96 SvxPaperBinItem* SvxPaperBinItem::Clone( SfxItemPool* ) const
97 {
98     return new SvxPaperBinItem( *this );
99 }
100 
101 bool SvxPaperBinItem::GetPresentation
102 (
103     SfxItemPresentation ePres,
104     MapUnit             /*eCoreUnit*/,
105     MapUnit             /*ePresUnit*/,
106     OUString&           rText, const IntlWrapper&
107 )   const
108 {
109     switch ( ePres )
110     {
111         case SfxItemPresentation::Nameless:
112             rText = OUString::number( GetValue() );
113             return true;
114 
115         case SfxItemPresentation::Complete:
116         {
117             sal_uInt8 nValue = GetValue();
118 
119             if ( PAPERBIN_PRINTER_SETTINGS == nValue )
120                 rText = EditResId(RID_SVXSTR_PAPERBIN_SETTINGS);
121             else
122             {
123                 rText = EditResId(RID_SVXSTR_PAPERBIN) + " " + OUString::number( nValue );
124             }
125             return true;
126         }
127         //no break necessary
128         default: ; //prevent warning
129     }
130 
131     return false;
132 }
133 
134 
135 SvxSizeItem::SvxSizeItem( const sal_uInt16 nId, const Size& rSize ) :
136 
137     SfxPoolItem( nId ),
138 
139     m_aSize( rSize )
140 {
141 }
142 
143 
144 bool SvxSizeItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
145 {
146     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
147     nMemberId &= ~CONVERT_TWIPS;
148 
149     awt::Size aTmp(m_aSize.Width(), m_aSize.Height());
150     if( bConvert )
151     {
152         aTmp.Height = convertTwipToMm100(aTmp.Height);
153         aTmp.Width = convertTwipToMm100(aTmp.Width);
154     }
155 
156     switch( nMemberId )
157     {
158         case MID_SIZE_SIZE:  rVal <<= aTmp; break;
159         case MID_SIZE_WIDTH: rVal <<= aTmp.Width; break;
160         case MID_SIZE_HEIGHT: rVal <<= aTmp.Height;  break;
161         default: OSL_FAIL("Wrong MemberId!"); return false;
162     }
163 
164     return true;
165 }
166 
167 
168 bool SvxSizeItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
169 {
170     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
171     nMemberId &= ~CONVERT_TWIPS;
172 
173     switch( nMemberId )
174     {
175         case MID_SIZE_SIZE:
176         {
177             awt::Size aTmp;
178             if( rVal >>= aTmp )
179             {
180                 if(bConvert)
181                 {
182                     aTmp.Height = convertMm100ToTwip(aTmp.Height);
183                     aTmp.Width = convertMm100ToTwip(aTmp.Width);
184                 }
185                 m_aSize = Size( aTmp.Width, aTmp.Height );
186             }
187             else
188             {
189                 return false;
190             }
191         }
192         break;
193         case MID_SIZE_WIDTH:
194         {
195             sal_Int32 nVal = 0;
196             if(!(rVal >>= nVal ))
197                 return false;
198 
199             m_aSize.setWidth( bConvert ? convertMm100ToTwip(nVal) : nVal );
200         }
201         break;
202         case MID_SIZE_HEIGHT:
203         {
204             sal_Int32 nVal = 0;
205             if(!(rVal >>= nVal))
206                 return true;
207 
208             m_aSize.setHeight( bConvert ? convertMm100ToTwip(nVal) : nVal );
209         }
210         break;
211         default: OSL_FAIL("Wrong MemberId!");
212             return false;
213     }
214     return true;
215 }
216 
217 
218 SvxSizeItem::SvxSizeItem( const sal_uInt16 nId ) :
219 
220     SfxPoolItem( nId )
221 {
222 }
223 
224 
225 bool SvxSizeItem::operator==( const SfxPoolItem& rAttr ) const
226 {
227     assert(SfxPoolItem::operator==(rAttr));
228 
229     return ( m_aSize == static_cast<const SvxSizeItem&>( rAttr ).GetSize() );
230 }
231 
232 SvxSizeItem* SvxSizeItem::Clone( SfxItemPool* ) const
233 {
234     return new SvxSizeItem( *this );
235 }
236 
237 bool SvxSizeItem::GetPresentation
238 (
239     SfxItemPresentation ePres,
240     MapUnit             eCoreUnit,
241     MapUnit             ePresUnit,
242     OUString&           rText, const IntlWrapper& rIntl
243 )   const
244 {
245     OUString cpDelimTmp(cpDelim);
246     switch ( ePres )
247     {
248         case SfxItemPresentation::Nameless:
249             rText = GetMetricText( m_aSize.Width(), eCoreUnit, ePresUnit, &rIntl ) +
250                     cpDelimTmp +
251                     GetMetricText( m_aSize.Height(), eCoreUnit, ePresUnit, &rIntl );
252             return true;
253 
254         case SfxItemPresentation::Complete:
255             rText = EditResId(RID_SVXITEMS_SIZE_WIDTH) +
256                     GetMetricText( m_aSize.Width(), eCoreUnit, ePresUnit, &rIntl ) +
257                     " " + EditResId(GetMetricId(ePresUnit)) +
258                     cpDelimTmp +
259                     EditResId(RID_SVXITEMS_SIZE_HEIGHT) +
260                     GetMetricText( m_aSize.Height(), eCoreUnit, ePresUnit, &rIntl ) +
261                     " " + EditResId(GetMetricId(ePresUnit));
262             return true;
263         // no break necessary
264         default: ; // prevent warning
265 
266     }
267     return false;
268 }
269 
270 
271 void SvxSizeItem::ScaleMetrics( long nMult, long nDiv )
272 {
273     m_aSize.setWidth( Scale( m_aSize.Width(), nMult, nDiv ) );
274     m_aSize.setHeight( Scale( m_aSize.Height(), nMult, nDiv ) );
275 }
276 
277 
278 bool SvxSizeItem::HasMetrics() const
279 {
280     return true;
281 }
282 
283 
284 SvxLRSpaceItem::SvxLRSpaceItem( const sal_uInt16 nId ) :
285 
286     SfxPoolItem( nId ),
287 
288     nTxtLeft        ( 0 ),
289     nLeftMargin     ( 0 ),
290     nRightMargin    ( 0 ),
291     nPropFirstLineOffset( 100 ),
292     nPropLeftMargin( 100 ),
293     nPropRightMargin( 100 ),
294     nFirstLineOffset  ( 0 ),
295     bAutoFirst      ( false ),
296     bExplicitZeroMarginValRight(false),
297     bExplicitZeroMarginValLeft(false)
298 {
299 }
300 
301 
302 SvxLRSpaceItem::SvxLRSpaceItem( const long nLeft, const long nRight,
303                                 const long nTLeft, const short nOfset,
304                                 const sal_uInt16 nId )
305 :   SfxPoolItem( nId ),
306 
307     nTxtLeft        ( nTLeft ),
308     nLeftMargin     ( nLeft ),
309     nRightMargin    ( nRight ),
310     nPropFirstLineOffset( 100 ),
311     nPropLeftMargin( 100 ),
312     nPropRightMargin( 100 ),
313     nFirstLineOffset  ( nOfset ),
314     bAutoFirst      ( false ),
315     bExplicitZeroMarginValRight(false),
316     bExplicitZeroMarginValLeft(false)
317 {
318 }
319 
320 
321 bool SvxLRSpaceItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
322 {
323     bool bRet = true;
324     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
325     nMemberId &= ~CONVERT_TWIPS;
326     switch( nMemberId )
327     {
328         // now all signed
329         case 0:
330         {
331             css::frame::status::LeftRightMarginScale aLRSpace;
332             aLRSpace.Left = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nLeftMargin) : nLeftMargin);
333             aLRSpace.TextLeft = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nTxtLeft) : nTxtLeft);
334             aLRSpace.Right = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nRightMargin) : nRightMargin);
335             aLRSpace.ScaleLeft = static_cast<sal_Int16>(nPropLeftMargin);
336             aLRSpace.ScaleRight = static_cast<sal_Int16>(nPropRightMargin);
337             aLRSpace.FirstLine = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nFirstLineOffset) : nFirstLineOffset);
338             aLRSpace.ScaleFirstLine = static_cast<sal_Int16>(nPropFirstLineOffset);
339             aLRSpace.AutoFirstLine = IsAutoFirst();
340             rVal <<= aLRSpace;
341             break;
342         }
343         case MID_L_MARGIN:
344             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nLeftMargin) : nLeftMargin);
345             break;
346 
347         case MID_TXT_LMARGIN :
348             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nTxtLeft) : nTxtLeft);
349         break;
350         case MID_R_MARGIN:
351             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nRightMargin) : nRightMargin);
352             break;
353         case MID_L_REL_MARGIN:
354             rVal <<= static_cast<sal_Int16>(nPropLeftMargin);
355         break;
356         case MID_R_REL_MARGIN:
357             rVal <<= static_cast<sal_Int16>(nPropRightMargin);
358         break;
359 
360         case MID_FIRST_LINE_INDENT:
361             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nFirstLineOffset) : nFirstLineOffset);
362             break;
363 
364         case MID_FIRST_LINE_REL_INDENT:
365             rVal <<= static_cast<sal_Int16>(nPropFirstLineOffset);
366             break;
367 
368         case MID_FIRST_AUTO:
369             rVal <<= IsAutoFirst();
370             break;
371 
372         default:
373             bRet = false;
374             // SfxDispatchController_Impl::StateChanged calls this with hardcoded 0 triggering this; there used to be a MID_LR_MARGIN 0 but what type would it have?
375             OSL_FAIL("unknown MemberId");
376     }
377     return bRet;
378 }
379 
380 
381 bool SvxLRSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
382 {
383     bool bConvert = 0 != (nMemberId&CONVERT_TWIPS);
384     nMemberId &= ~CONVERT_TWIPS;
385     sal_Int32 nVal = 0;
386     if( nMemberId != 0 && nMemberId != MID_FIRST_AUTO &&
387             nMemberId != MID_L_REL_MARGIN && nMemberId != MID_R_REL_MARGIN)
388         if(!(rVal >>= nVal))
389             return false;
390 
391     switch( nMemberId )
392     {
393         case 0:
394         {
395             css::frame::status::LeftRightMarginScale aLRSpace;
396             if(!(rVal >>= aLRSpace))
397                 return false;
398 
399             SetLeft( bConvert ? convertMm100ToTwip(aLRSpace.Left) : aLRSpace.Left );
400             SetTextLeft( bConvert ? convertMm100ToTwip(aLRSpace.TextLeft) : aLRSpace.TextLeft );
401             SetRight(bConvert ? convertMm100ToTwip(aLRSpace.Right) : aLRSpace.Right);
402             nPropLeftMargin = aLRSpace.ScaleLeft;
403             nPropRightMargin = aLRSpace.ScaleRight;
404             SetTextFirstLineOffset(static_cast<short>(bConvert ?  convertMm100ToTwip(aLRSpace.FirstLine) : aLRSpace.FirstLine));
405             SetPropTextFirstLineOffset ( static_cast<sal_uInt16>(aLRSpace.ScaleFirstLine) );
406             SetAutoFirst( aLRSpace.AutoFirstLine );
407             break;
408         }
409         case MID_L_MARGIN:
410             SetLeft( bConvert ? convertMm100ToTwip(nVal) : nVal );
411             break;
412 
413         case MID_TXT_LMARGIN :
414             SetTextLeft( bConvert ? convertMm100ToTwip(nVal) : nVal );
415         break;
416 
417         case MID_R_MARGIN:
418             SetRight(bConvert ? convertMm100ToTwip(nVal) : nVal);
419             break;
420         case MID_L_REL_MARGIN:
421         case MID_R_REL_MARGIN:
422         {
423             sal_Int32 nRel = 0;
424             if((rVal >>= nRel) && nRel >= 0 && nRel < SAL_MAX_UINT16)
425             {
426                 if(MID_L_REL_MARGIN== nMemberId)
427                     nPropLeftMargin = static_cast<sal_uInt16>(nRel);
428                 else
429                     nPropRightMargin = static_cast<sal_uInt16>(nRel);
430             }
431             else
432                 return false;
433         }
434         break;
435         case MID_FIRST_LINE_INDENT     :
436             SetTextFirstLineOffset(static_cast<short>(bConvert ?  convertMm100ToTwip(nVal) : nVal));
437             break;
438 
439         case MID_FIRST_LINE_REL_INDENT:
440             SetPropTextFirstLineOffset ( static_cast<sal_uInt16>(nVal) );
441             break;
442 
443         case MID_FIRST_AUTO:
444             SetAutoFirst( Any2Bool(rVal) );
445             break;
446 
447         default:
448             OSL_FAIL("unknown MemberId");
449             return false;
450     }
451     return true;
452 }
453 
454 
455 /// Adapt nLeftMargin and nTxtLeft.
456 void SvxLRSpaceItem::AdjustLeft()
457 {
458     if ( 0 > nFirstLineOffset )
459         nLeftMargin = nTxtLeft + nFirstLineOffset;
460     else
461         nLeftMargin = nTxtLeft;
462 }
463 
464 
465 bool SvxLRSpaceItem::operator==( const SfxPoolItem& rAttr ) const
466 {
467     assert(SfxPoolItem::operator==(rAttr));
468 
469     const SvxLRSpaceItem& rOther = static_cast<const SvxLRSpaceItem&>(rAttr);
470 
471     return (
472         nFirstLineOffset == rOther.GetTextFirstLineOffset() &&
473         nTxtLeft == rOther.GetTextLeft() &&
474         nLeftMargin == rOther.GetLeft()  &&
475         nRightMargin == rOther.GetRight() &&
476         nPropFirstLineOffset == rOther.GetPropTextFirstLineOffset() &&
477         nPropLeftMargin == rOther.GetPropLeft()  &&
478         nPropRightMargin == rOther.GetPropRight() &&
479         bAutoFirst == rOther.IsAutoFirst() &&
480         bExplicitZeroMarginValRight == rOther.IsExplicitZeroMarginValRight() &&
481         bExplicitZeroMarginValLeft == rOther.IsExplicitZeroMarginValLeft() );
482 }
483 
484 SvxLRSpaceItem* SvxLRSpaceItem::Clone( SfxItemPool* ) const
485 {
486     return new SvxLRSpaceItem( *this );
487 }
488 
489 bool SvxLRSpaceItem::GetPresentation
490 (
491     SfxItemPresentation ePres,
492     MapUnit             eCoreUnit,
493     MapUnit             ePresUnit,
494     OUString&           rText, const IntlWrapper& rIntl
495 )   const
496 {
497     switch ( ePres )
498     {
499         case SfxItemPresentation::Nameless:
500         {
501             if ( 100 != nPropLeftMargin )
502             {
503                 rText = unicode::formatPercent(nPropLeftMargin,
504                     Application::GetSettings().GetUILanguageTag());
505             }
506             else
507                 rText = GetMetricText( nLeftMargin,
508                                        eCoreUnit, ePresUnit, &rIntl );
509             rText += OUString(cpDelim);
510             if ( 100 != nPropFirstLineOffset )
511             {
512                 rText += unicode::formatPercent(nPropFirstLineOffset,
513                     Application::GetSettings().GetUILanguageTag());
514             }
515             else
516                 rText += GetMetricText( static_cast<long>(nFirstLineOffset),
517                                         eCoreUnit, ePresUnit, &rIntl );
518             rText += OUString(cpDelim);
519             if ( 100 != nRightMargin )
520             {
521                 rText += unicode::formatPercent(nRightMargin,
522                     Application::GetSettings().GetUILanguageTag());
523             }
524             else
525                 rText += GetMetricText( nRightMargin,
526                                         eCoreUnit, ePresUnit, &rIntl );
527             return true;
528         }
529         case SfxItemPresentation::Complete:
530         {
531             rText = EditResId(RID_SVXITEMS_LRSPACE_LEFT);
532             if ( 100 != nPropLeftMargin )
533                 rText += unicode::formatPercent(nPropLeftMargin,
534                     Application::GetSettings().GetUILanguageTag());
535             else
536             {
537                 rText += GetMetricText( nLeftMargin, eCoreUnit, ePresUnit, &rIntl ) +
538                         " " + EditResId(GetMetricId(ePresUnit));
539             }
540             rText += OUString(cpDelim);
541             if ( 100 != nPropFirstLineOffset || nFirstLineOffset )
542             {
543                 rText += EditResId(RID_SVXITEMS_LRSPACE_FLINE);
544                 if ( 100 != nPropFirstLineOffset )
545                     rText += unicode::formatPercent(nPropFirstLineOffset,
546                                 Application::GetSettings().GetUILanguageTag());
547                 else
548                 {
549                     rText += GetMetricText( static_cast<long>(nFirstLineOffset),
550                                             eCoreUnit, ePresUnit, &rIntl ) +
551                             " " + EditResId(GetMetricId(ePresUnit));
552                 }
553                 rText += OUString(cpDelim);
554             }
555             rText += EditResId(RID_SVXITEMS_LRSPACE_RIGHT);
556             if ( 100 != nPropRightMargin )
557                 rText += unicode::formatPercent(nPropRightMargin,
558                     Application::GetSettings().GetUILanguageTag());
559             else
560             {
561                 rText += GetMetricText( nRightMargin,
562                                        eCoreUnit, ePresUnit, &rIntl ) +
563                         " " + EditResId(GetMetricId(ePresUnit));
564             }
565             return true;
566         }
567         default: ; // prevent warning
568     }
569     return false;
570 }
571 
572 
573 void SvxLRSpaceItem::ScaleMetrics( long nMult, long nDiv )
574 {
575     nFirstLineOffset = static_cast<short>(Scale( nFirstLineOffset, nMult, nDiv ));
576     nTxtLeft = Scale( nTxtLeft, nMult, nDiv );
577     nLeftMargin = Scale( nLeftMargin, nMult, nDiv );
578     nRightMargin = Scale( nRightMargin, nMult, nDiv );
579 }
580 
581 
582 bool SvxLRSpaceItem::HasMetrics() const
583 {
584     return true;
585 }
586 
587 
588 void SvxLRSpaceItem::dumpAsXml(xmlTextWriterPtr pWriter) const
589 {
590     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxLRSpaceItem"));
591     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
592     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nFirstLineOffset"), BAD_CAST(OString::number(nFirstLineOffset).getStr()));
593     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nTxtLeft"), BAD_CAST(OString::number(nTxtLeft).getStr()));
594     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nLeftMargin"), BAD_CAST(OString::number(nLeftMargin).getStr()));
595     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nRightMargin"), BAD_CAST(OString::number(nRightMargin).getStr()));
596     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropFirstLineOffset"), BAD_CAST(OString::number(nPropFirstLineOffset).getStr()));
597     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropLeftMargin"), BAD_CAST(OString::number(nPropLeftMargin).getStr()));
598     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropRightMargin"), BAD_CAST(OString::number(nPropRightMargin).getStr()));
599     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("bAutoFirst"), BAD_CAST(OString::number(int(bAutoFirst)).getStr()));
600     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("bExplicitZeroMarginValRight"), BAD_CAST(OString::number(int(bExplicitZeroMarginValRight)).getStr()));
601     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("bExplicitZeroMarginValLeft"), BAD_CAST(OString::number(int(bExplicitZeroMarginValLeft)).getStr()));
602     xmlTextWriterEndElement(pWriter);
603 }
604 
605 
606 boost::property_tree::ptree SvxLRSpaceItem::dumpAsJSON() const
607 {
608     boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
609 
610     boost::property_tree::ptree aState;
611 
612     MapUnit eTargetUnit = MapUnit::MapInch;
613 
614     OUString sLeft = GetMetricText(GetLeft(),
615                         MapUnit::MapTwip, eTargetUnit, nullptr);
616 
617     OUString sRight = GetMetricText(GetRight(),
618                         MapUnit::MapTwip, eTargetUnit, nullptr);
619 
620     OUString sFirstline = GetMetricText(GetTextFirstLineOffset(),
621                         MapUnit::MapTwip, eTargetUnit, nullptr);
622 
623     aState.put("left", sLeft);
624     aState.put("right", sRight);
625     aState.put("firstline", sFirstline);
626     aState.put("unit", "inch");
627 
628     aTree.push_back(std::make_pair("state", aState));
629 
630     return aTree;
631 }
632 
633 
634 SvxULSpaceItem::SvxULSpaceItem( const sal_uInt16 nId )
635     : SfxPoolItem(nId)
636     , nUpper(0)
637     , nLower(0)
638     , bContext(false)
639     , nPropUpper(100)
640     , nPropLower(100)
641 {
642 }
643 
644 
645 SvxULSpaceItem::SvxULSpaceItem( const sal_uInt16 nUp, const sal_uInt16 nLow,
646                                 const sal_uInt16 nId )
647     : SfxPoolItem(nId)
648     , nUpper(nUp)
649     , nLower(nLow)
650     , bContext(false)
651     , nPropUpper(100)
652     , nPropLower(100)
653 {
654 }
655 
656 
657 bool SvxULSpaceItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
658 {
659     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
660     nMemberId &= ~CONVERT_TWIPS;
661     switch( nMemberId )
662     {
663         // now all signed
664         case 0:
665         {
666             css::frame::status::UpperLowerMarginScale aUpperLowerMarginScale;
667             aUpperLowerMarginScale.Upper = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nUpper) : nUpper);
668             aUpperLowerMarginScale.Lower = static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nLower) : nPropUpper);
669             aUpperLowerMarginScale.ScaleUpper = static_cast<sal_Int16>(nPropUpper);
670             aUpperLowerMarginScale.ScaleLower = static_cast<sal_Int16>(nPropLower);
671             rVal <<= aUpperLowerMarginScale;
672             break;
673         }
674         case MID_UP_MARGIN: rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nUpper) : nUpper); break;
675         case MID_LO_MARGIN: rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nLower) : nLower); break;
676         case MID_CTX_MARGIN: rVal <<= bContext; break;
677         case MID_UP_REL_MARGIN: rVal <<= static_cast<sal_Int16>(nPropUpper); break;
678         case MID_LO_REL_MARGIN: rVal <<= static_cast<sal_Int16>(nPropLower); break;
679     }
680     return true;
681 }
682 
683 
684 bool SvxULSpaceItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
685 {
686     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
687     nMemberId &= ~CONVERT_TWIPS;
688     sal_Int32 nVal = 0;
689     bool bVal = false;
690     switch( nMemberId )
691     {
692         case 0:
693         {
694             css::frame::status::UpperLowerMarginScale aUpperLowerMarginScale;
695             if ( !(rVal >>= aUpperLowerMarginScale ))
696                 return false;
697             {
698                 SetUpper(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip( aUpperLowerMarginScale.Upper ) : aUpperLowerMarginScale.Upper));
699                 SetLower(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip( aUpperLowerMarginScale.Lower ) : aUpperLowerMarginScale.Lower));
700                 if( aUpperLowerMarginScale.ScaleUpper > 1 )
701                     nPropUpper = aUpperLowerMarginScale.ScaleUpper;
702                 if( aUpperLowerMarginScale.ScaleLower > 1 )
703                     nPropUpper = aUpperLowerMarginScale.ScaleLower;
704             }
705         }
706         break;
707         case MID_UP_MARGIN :
708             if(!(rVal >>= nVal) || nVal < 0)
709                 return false;
710             SetUpper(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip(nVal) : nVal));
711             break;
712         case MID_LO_MARGIN :
713             if(!(rVal >>= nVal) || nVal < 0)
714                 return false;
715             SetLower(static_cast<sal_uInt16>(bConvert ? convertMm100ToTwip(nVal) : nVal));
716             break;
717         case MID_CTX_MARGIN :
718             if (!(rVal >>= bVal))
719                 return false;
720             SetContextValue(bVal);
721             break;
722         case MID_UP_REL_MARGIN:
723         case MID_LO_REL_MARGIN:
724         {
725             sal_Int32 nRel = 0;
726             if((rVal >>= nRel) && nRel > 1 )
727             {
728                 if(MID_UP_REL_MARGIN == nMemberId)
729                     nPropUpper = static_cast<sal_uInt16>(nRel);
730                 else
731                     nPropLower = static_cast<sal_uInt16>(nRel);
732             }
733             else
734                 return false;
735         }
736         break;
737 
738         default:
739             OSL_FAIL("unknown MemberId");
740             return false;
741     }
742     return true;
743 }
744 
745 
746 bool SvxULSpaceItem::operator==( const SfxPoolItem& rAttr ) const
747 {
748     assert(SfxPoolItem::operator==(rAttr));
749 
750     const SvxULSpaceItem& rSpaceItem = static_cast<const SvxULSpaceItem&>( rAttr );
751     return ( nUpper == rSpaceItem.nUpper &&
752              nLower == rSpaceItem.nLower &&
753              bContext == rSpaceItem.bContext &&
754              nPropUpper == rSpaceItem.nPropUpper &&
755              nPropLower == rSpaceItem.nPropLower );
756 }
757 
758 SvxULSpaceItem* SvxULSpaceItem::Clone( SfxItemPool* ) const
759 {
760     return new SvxULSpaceItem( *this );
761 }
762 
763 bool SvxULSpaceItem::GetPresentation
764 (
765     SfxItemPresentation ePres,
766     MapUnit             eCoreUnit,
767     MapUnit             ePresUnit,
768     OUString&           rText,
769     const IntlWrapper&  rIntl
770 )   const
771 {
772     switch ( ePres )
773     {
774         case SfxItemPresentation::Nameless:
775         {
776             if ( 100 != nPropUpper )
777             {
778                 rText = unicode::formatPercent(nPropUpper,
779                     Application::GetSettings().GetUILanguageTag());
780             }
781             else
782                 rText = GetMetricText( static_cast<long>(nUpper), eCoreUnit, ePresUnit, &rIntl );
783             rText += OUString(cpDelim);
784             if ( 100 != nPropLower )
785             {
786                 rText += unicode::formatPercent(nPropLower,
787                     Application::GetSettings().GetUILanguageTag());
788             }
789             else
790                 rText += GetMetricText( static_cast<long>(nLower), eCoreUnit, ePresUnit, &rIntl );
791             return true;
792         }
793         case SfxItemPresentation::Complete:
794         {
795             rText = EditResId(RID_SVXITEMS_ULSPACE_UPPER);
796             if ( 100 != nPropUpper )
797             {
798                 rText += unicode::formatPercent(nPropUpper,
799                     Application::GetSettings().GetUILanguageTag());
800             }
801             else
802             {
803                 rText += GetMetricText( static_cast<long>(nUpper), eCoreUnit, ePresUnit, &rIntl ) +
804                         " " + EditResId(GetMetricId(ePresUnit));
805             }
806             rText += cpDelim + EditResId(RID_SVXITEMS_ULSPACE_LOWER);
807             if ( 100 != nPropLower )
808             {
809                 rText += unicode::formatPercent(nPropLower,
810                     Application::GetSettings().GetUILanguageTag());
811             }
812             else
813             {
814                 rText += GetMetricText( static_cast<long>(nLower), eCoreUnit, ePresUnit, &rIntl ) +
815                         " " + EditResId(GetMetricId(ePresUnit));
816             }
817             return true;
818         }
819         default: ; // prevent warning
820     }
821     return false;
822 }
823 
824 
825 void SvxULSpaceItem::ScaleMetrics( long nMult, long nDiv )
826 {
827     nUpper = static_cast<sal_uInt16>(Scale( nUpper, nMult, nDiv ));
828     nLower = static_cast<sal_uInt16>(Scale( nLower, nMult, nDiv ));
829 }
830 
831 
832 bool SvxULSpaceItem::HasMetrics() const
833 {
834     return true;
835 }
836 
837 
838 void SvxULSpaceItem::dumpAsXml(xmlTextWriterPtr pWriter) const
839 {
840     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxULSpaceItem"));
841     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
842     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nUpper"), BAD_CAST(OString::number(nUpper).getStr()));
843     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nLower"), BAD_CAST(OString::number(nLower).getStr()));
844     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("bContext"), BAD_CAST(OString::boolean(bContext).getStr()));
845     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropUpper"), BAD_CAST(OString::number(nPropUpper).getStr()));
846     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nPropLower"), BAD_CAST(OString::number(nPropLower).getStr()));
847     xmlTextWriterEndElement(pWriter);
848 }
849 
850 boost::property_tree::ptree SvxULSpaceItem::dumpAsJSON() const
851 {
852     boost::property_tree::ptree aTree = SfxPoolItem::dumpAsJSON();
853 
854     boost::property_tree::ptree aState;
855 
856     MapUnit eTargetUnit = MapUnit::MapInch;
857 
858     OUString sUpper = GetMetricText(GetUpper(),
859                         MapUnit::MapTwip, eTargetUnit, nullptr);
860 
861     OUString sLower = GetMetricText(GetLower(),
862                         MapUnit::MapTwip, eTargetUnit, nullptr);
863 
864     aState.put("upper", sUpper);
865     aState.put("lower", sLower);
866     aState.put("unit", "inch");
867 
868     aTree.push_back(std::make_pair("state", aState));
869 
870     return aTree;
871 }
872 
873 SvxPrintItem* SvxPrintItem::Clone( SfxItemPool* ) const
874 {
875     return new SvxPrintItem( *this );
876 }
877 
878 bool SvxPrintItem::GetPresentation
879 (
880     SfxItemPresentation /*ePres*/,
881     MapUnit             /*eCoreUnit*/,
882     MapUnit             /*ePresUnit*/,
883     OUString&           rText, const IntlWrapper&
884 )   const
885 {
886     const char* pId = RID_SVXITEMS_PRINT_FALSE;
887 
888     if ( GetValue() )
889         pId = RID_SVXITEMS_PRINT_TRUE;
890     rText = EditResId(pId);
891     return true;
892 }
893 
894 SvxOpaqueItem* SvxOpaqueItem::Clone( SfxItemPool* ) const
895 {
896     return new SvxOpaqueItem( *this );
897 }
898 
899 bool SvxOpaqueItem::GetPresentation
900 (
901     SfxItemPresentation /*ePres*/,
902     MapUnit             /*eCoreUnit*/,
903     MapUnit             /*ePresUnit*/,
904     OUString&           rText, const IntlWrapper&
905 )   const
906 {
907     const char* pId = RID_SVXITEMS_OPAQUE_FALSE;
908 
909     if ( GetValue() )
910         pId = RID_SVXITEMS_OPAQUE_TRUE;
911     rText = EditResId(pId);
912     return true;
913 }
914 
915 
916 bool SvxProtectItem::operator==( const SfxPoolItem& rAttr ) const
917 {
918     assert(SfxPoolItem::operator==(rAttr));
919 
920     const SvxProtectItem& rItem = static_cast<const SvxProtectItem&>(rAttr);
921     return ( bCntnt == rItem.bCntnt &&
922              bSize  == rItem.bSize  &&
923              bPos   == rItem.bPos );
924 }
925 
926 
927 bool SvxProtectItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
928 {
929     nMemberId &= ~CONVERT_TWIPS;
930     bool bValue;
931     switch(nMemberId)
932     {
933         case MID_PROTECT_CONTENT :  bValue = bCntnt; break;
934         case MID_PROTECT_SIZE    :  bValue = bSize; break;
935         case MID_PROTECT_POSITION:  bValue = bPos; break;
936         default:
937             OSL_FAIL("Wrong MemberId");
938             return false;
939     }
940 
941     rVal <<= bValue;
942     return true;
943 }
944 
945 
946 bool SvxProtectItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
947 {
948     nMemberId &= ~CONVERT_TWIPS;
949     bool bVal( Any2Bool(rVal) );
950     switch(nMemberId)
951     {
952         case MID_PROTECT_CONTENT :  bCntnt = bVal;  break;
953         case MID_PROTECT_SIZE    :  bSize  = bVal;  break;
954         case MID_PROTECT_POSITION:  bPos   = bVal;  break;
955         default:
956             OSL_FAIL("Wrong MemberId");
957             return false;
958     }
959     return true;
960 }
961 
962 SvxProtectItem* SvxProtectItem::Clone( SfxItemPool* ) const
963 {
964     return new SvxProtectItem( *this );
965 }
966 
967 bool SvxProtectItem::GetPresentation
968 (
969     SfxItemPresentation /*ePres*/,
970     MapUnit             /*eCoreUnit*/,
971     MapUnit             /*ePresUnit*/,
972     OUString&           rText, const IntlWrapper&
973 )   const
974 {
975     const char* pId = RID_SVXITEMS_PROT_CONTENT_FALSE;
976 
977     if ( bCntnt )
978         pId = RID_SVXITEMS_PROT_CONTENT_TRUE;
979     rText = EditResId(pId) + cpDelim;
980     pId = RID_SVXITEMS_PROT_SIZE_FALSE;
981 
982     if ( bSize )
983         pId = RID_SVXITEMS_PROT_SIZE_TRUE;
984     rText += EditResId(pId) + cpDelim;
985     pId = RID_SVXITEMS_PROT_POS_FALSE;
986 
987     if ( bPos )
988         pId = RID_SVXITEMS_PROT_POS_TRUE;
989     rText += EditResId(pId);
990     return true;
991 }
992 
993 
994 void SvxProtectItem::dumpAsXml(xmlTextWriterPtr pWriter) const
995 {
996     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxProtectItem"));
997     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
998     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("content"), BAD_CAST(OString::boolean(bCntnt).getStr()));
999     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("size"), BAD_CAST(OString::boolean(bSize).getStr()));
1000     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("position"), BAD_CAST(OString::boolean(bPos).getStr()));
1001     xmlTextWriterEndElement(pWriter);
1002 }
1003 
1004 
1005 SvxShadowItem::SvxShadowItem( const sal_uInt16 nId,
1006                  const Color *pColor, const sal_uInt16 nW,
1007                  const SvxShadowLocation eLoc ) :
1008     SfxEnumItemInterface( nId ),
1009     aShadowColor(COL_GRAY),
1010     nWidth      ( nW ),
1011     eLocation   ( eLoc )
1012 {
1013     if ( pColor )
1014         aShadowColor = *pColor;
1015 }
1016 
1017 
1018 bool SvxShadowItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
1019 {
1020     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
1021     nMemberId &= ~CONVERT_TWIPS;
1022 
1023     table::ShadowFormat aShadow;
1024     table::ShadowLocation eSet = table::ShadowLocation_NONE;
1025     switch( eLocation )
1026     {
1027         case SvxShadowLocation::TopLeft    : eSet = table::ShadowLocation_TOP_LEFT    ; break;
1028         case SvxShadowLocation::TopRight   : eSet = table::ShadowLocation_TOP_RIGHT   ; break;
1029         case SvxShadowLocation::BottomLeft : eSet = table::ShadowLocation_BOTTOM_LEFT ; break;
1030         case SvxShadowLocation::BottomRight: eSet = table::ShadowLocation_BOTTOM_RIGHT; break;
1031         default: ; // prevent warning
1032     }
1033     aShadow.Location = eSet;
1034     aShadow.ShadowWidth =   bConvert ? convertTwipToMm100(nWidth) : nWidth;
1035     aShadow.IsTransparent = aShadowColor.GetTransparency() > 0;
1036     aShadow.Color = sal_Int32(aShadowColor);
1037 
1038     sal_Int8 nTransparence = rtl::math::round(float(aShadowColor.GetTransparency() * 100) / 255);
1039 
1040     switch ( nMemberId )
1041     {
1042         case MID_LOCATION: rVal <<= aShadow.Location; break;
1043         case MID_WIDTH: rVal <<= aShadow.ShadowWidth; break;
1044         case MID_TRANSPARENT: rVal <<= aShadow.IsTransparent; break;
1045         case MID_BG_COLOR: rVal <<= aShadow.Color; break;
1046         case 0: rVal <<= aShadow; break;
1047         case MID_SHADOW_TRANSPARENCE: rVal <<= nTransparence; break;
1048         default: OSL_FAIL("Wrong MemberId!"); return false;
1049     }
1050 
1051     return true;
1052 }
1053 
1054 bool SvxShadowItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
1055 {
1056     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
1057     nMemberId &= ~CONVERT_TWIPS;
1058 
1059     table::ShadowFormat aShadow;
1060     uno::Any aAny;
1061     bool bRet = QueryValue( aAny, bConvert ? CONVERT_TWIPS : 0 ) && ( aAny >>= aShadow );
1062     switch ( nMemberId )
1063     {
1064         case MID_LOCATION:
1065         {
1066             bRet = (rVal >>= aShadow.Location);
1067             if ( !bRet )
1068             {
1069                 sal_Int16 nVal = 0;
1070                 bRet = (rVal >>= nVal);
1071                 aShadow.Location = static_cast<table::ShadowLocation>(nVal);
1072             }
1073 
1074             break;
1075         }
1076 
1077         case MID_WIDTH: rVal >>= aShadow.ShadowWidth; break;
1078         case MID_TRANSPARENT: rVal >>= aShadow.IsTransparent; break;
1079         case MID_BG_COLOR: rVal >>= aShadow.Color; break;
1080         case 0: rVal >>= aShadow; break;
1081         case MID_SHADOW_TRANSPARENCE:
1082         {
1083             sal_Int32 nTransparence = 0;
1084             if ((rVal >>= nTransparence) && !o3tl::checked_multiply<sal_Int32>(nTransparence, 255, nTransparence))
1085             {
1086                 Color aColor(aShadow.Color);
1087                 aColor.SetTransparency(rtl::math::round(float(nTransparence) / 100));
1088                 aShadow.Color = sal_Int32(aColor);
1089             }
1090             break;
1091         }
1092         default: OSL_FAIL("Wrong MemberId!"); return false;
1093     }
1094 
1095     if ( bRet )
1096     {
1097         switch( aShadow.Location )
1098         {
1099             case table::ShadowLocation_NONE        : eLocation = SvxShadowLocation::NONE; break;
1100             case table::ShadowLocation_TOP_LEFT    : eLocation = SvxShadowLocation::TopLeft; break;
1101             case table::ShadowLocation_TOP_RIGHT   : eLocation = SvxShadowLocation::TopRight; break;
1102             case table::ShadowLocation_BOTTOM_LEFT : eLocation = SvxShadowLocation::BottomLeft ; break;
1103             case table::ShadowLocation_BOTTOM_RIGHT: eLocation = SvxShadowLocation::BottomRight; break;
1104             default: ; // prevent warning
1105         }
1106 
1107         nWidth = bConvert ? convertMm100ToTwip(aShadow.ShadowWidth) : aShadow.ShadowWidth;
1108         Color aSet(aShadow.Color);
1109         aShadowColor = aSet;
1110     }
1111 
1112     return bRet;
1113 }
1114 
1115 
1116 bool SvxShadowItem::operator==( const SfxPoolItem& rAttr ) const
1117 {
1118     assert(SfxPoolItem::operator==(rAttr));
1119 
1120     const SvxShadowItem& rItem = static_cast<const SvxShadowItem&>(rAttr);
1121     return ( ( aShadowColor == rItem.aShadowColor ) &&
1122              ( nWidth    == rItem.GetWidth() ) &&
1123              ( eLocation == rItem.GetLocation() ) );
1124 }
1125 
1126 SvxShadowItem* SvxShadowItem::Clone( SfxItemPool* ) const
1127 {
1128     return new SvxShadowItem( *this );
1129 }
1130 
1131 sal_uInt16 SvxShadowItem::CalcShadowSpace( SvxShadowItemSide nShadow ) const
1132 {
1133     sal_uInt16 nSpace = 0;
1134 
1135     switch ( nShadow )
1136     {
1137         case SvxShadowItemSide::TOP:
1138             if ( eLocation == SvxShadowLocation::TopLeft ||
1139                  eLocation == SvxShadowLocation::TopRight  )
1140                 nSpace = nWidth;
1141             break;
1142 
1143         case SvxShadowItemSide::BOTTOM:
1144             if ( eLocation == SvxShadowLocation::BottomLeft ||
1145                  eLocation == SvxShadowLocation::BottomRight  )
1146                 nSpace = nWidth;
1147             break;
1148 
1149         case SvxShadowItemSide::LEFT:
1150             if ( eLocation == SvxShadowLocation::TopLeft ||
1151                  eLocation == SvxShadowLocation::BottomLeft )
1152                 nSpace = nWidth;
1153             break;
1154 
1155         case SvxShadowItemSide::RIGHT:
1156             if ( eLocation == SvxShadowLocation::TopRight ||
1157                  eLocation == SvxShadowLocation::BottomRight )
1158                 nSpace = nWidth;
1159             break;
1160 
1161         default:
1162             OSL_FAIL( "wrong shadow" );
1163     }
1164     return nSpace;
1165 }
1166 
1167 static const char* RID_SVXITEMS_SHADOW[] =
1168 {
1169     RID_SVXITEMS_SHADOW_NONE,
1170     RID_SVXITEMS_SHADOW_TOPLEFT,
1171     RID_SVXITEMS_SHADOW_TOPRIGHT,
1172     RID_SVXITEMS_SHADOW_BOTTOMLEFT,
1173     RID_SVXITEMS_SHADOW_BOTTOMRIGHT
1174 };
1175 
1176 bool SvxShadowItem::GetPresentation
1177 (
1178     SfxItemPresentation ePres,
1179     MapUnit             eCoreUnit,
1180     MapUnit             ePresUnit,
1181     OUString&           rText, const IntlWrapper& rIntl
1182 )   const
1183 {
1184     switch ( ePres )
1185     {
1186         case SfxItemPresentation::Nameless:
1187         {
1188             rText = ::GetColorString( aShadowColor ) + cpDelim;
1189             const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE;
1190 
1191             if ( aShadowColor.GetTransparency() )
1192                 pId = RID_SVXITEMS_TRANSPARENT_TRUE;
1193             rText += EditResId(pId) +
1194                     cpDelim +
1195                     GetMetricText( static_cast<long>(nWidth), eCoreUnit, ePresUnit, &rIntl ) +
1196                     cpDelim +
1197                     EditResId(RID_SVXITEMS_SHADOW[static_cast<int>(eLocation)]);
1198             return true;
1199         }
1200         case SfxItemPresentation::Complete:
1201         {
1202             rText = EditResId(RID_SVXITEMS_SHADOW_COMPLETE) +
1203                     ::GetColorString( aShadowColor ) +
1204                     cpDelim;
1205 
1206             const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE;
1207             if ( aShadowColor.GetTransparency() )
1208                 pId = RID_SVXITEMS_TRANSPARENT_TRUE;
1209             rText += EditResId(pId) +
1210                     cpDelim +
1211                     GetMetricText( static_cast<long>(nWidth), eCoreUnit, ePresUnit, &rIntl ) +
1212                     " " + EditResId(GetMetricId(ePresUnit)) +
1213                     cpDelim +
1214                     EditResId(RID_SVXITEMS_SHADOW[static_cast<int>(eLocation)]);
1215             return true;
1216         }
1217         default: ; // prevent warning
1218     }
1219     return false;
1220 }
1221 
1222 
1223 void SvxShadowItem::ScaleMetrics( long nMult, long nDiv )
1224 {
1225     nWidth = static_cast<sal_uInt16>(Scale( nWidth, nMult, nDiv ));
1226 }
1227 
1228 
1229 bool SvxShadowItem::HasMetrics() const
1230 {
1231     return true;
1232 }
1233 
1234 
1235 sal_uInt16 SvxShadowItem::GetValueCount() const
1236 {
1237     return sal_uInt16(SvxShadowLocation::End);  // SvxShadowLocation::BottomRight + 1
1238 }
1239 
1240 sal_uInt16 SvxShadowItem::GetEnumValue() const
1241 {
1242     return static_cast<sal_uInt16>(GetLocation());
1243 }
1244 
1245 
1246 void SvxShadowItem::SetEnumValue( sal_uInt16 nVal )
1247 {
1248     SetLocation( static_cast<SvxShadowLocation>(nVal) );
1249 }
1250 
1251 void SvxShadowItem::dumpAsXml(xmlTextWriterPtr pWriter) const
1252 {
1253     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxShadowItem"));
1254     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
1255     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("aShadowColor"), BAD_CAST(aShadowColor.AsRGBHexString().toUtf8().getStr()));
1256     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nWidth"), BAD_CAST(OString::number(nWidth).getStr()));
1257     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("eLocation"), BAD_CAST(OString::number(static_cast<int>(eLocation)).getStr()));
1258     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("presentation"), BAD_CAST(EditResId(RID_SVXITEMS_SHADOW[static_cast<int>(eLocation)]).toUtf8().getStr()));
1259     xmlTextWriterEndElement(pWriter);
1260 }
1261 
1262 // class SvxBoxItem ------------------------------------------------------
1263 
1264 SvxBoxItem::SvxBoxItem( const SvxBoxItem& rCpy ) :
1265 
1266     SfxPoolItem ( rCpy ),
1267     pTop        ( rCpy.pTop     ? new SvxBorderLine( *rCpy.pTop )    : nullptr ),
1268     pBottom     ( rCpy.pBottom  ? new SvxBorderLine( *rCpy.pBottom ) : nullptr ),
1269     pLeft       ( rCpy.pLeft    ? new SvxBorderLine( *rCpy.pLeft )   : nullptr ),
1270     pRight      ( rCpy.pRight   ? new SvxBorderLine( *rCpy.pRight )  : nullptr ),
1271     nTopDist    ( rCpy.nTopDist ),
1272     nBottomDist ( rCpy.nBottomDist ),
1273     nLeftDist   ( rCpy.nLeftDist ),
1274     nRightDist  ( rCpy.nRightDist ),
1275     bRemoveAdjCellBorder ( rCpy.bRemoveAdjCellBorder )
1276 {
1277 }
1278 
1279 
1280 SvxBoxItem::SvxBoxItem( const sal_uInt16 nId ) :
1281     SfxPoolItem( nId ),
1282     nTopDist    ( 0 ),
1283     nBottomDist ( 0 ),
1284     nLeftDist   ( 0 ),
1285     nRightDist  ( 0 ),
1286     bRemoveAdjCellBorder ( false )
1287 {
1288 }
1289 
1290 
1291 SvxBoxItem::~SvxBoxItem()
1292 {
1293 }
1294 
1295 
1296 static bool CmpBrdLn( const std::unique_ptr<SvxBorderLine> & pBrd1, const SvxBorderLine* pBrd2 )
1297 {
1298     if( pBrd1.get() == pBrd2 )
1299         return true;
1300     if( pBrd1 == nullptr || pBrd2 == nullptr)
1301         return false;
1302     return *pBrd1 == *pBrd2;
1303 }
1304 
1305 
1306 bool SvxBoxItem::operator==( const SfxPoolItem& rAttr ) const
1307 {
1308     assert(SfxPoolItem::operator==(rAttr));
1309 
1310     const SvxBoxItem& rBoxItem = static_cast<const SvxBoxItem&>(rAttr);
1311     return (
1312         ( nTopDist == rBoxItem.nTopDist ) &&
1313         ( nBottomDist == rBoxItem.nBottomDist )   &&
1314         ( nLeftDist == rBoxItem.nLeftDist )   &&
1315         ( nRightDist == rBoxItem.nRightDist ) &&
1316         ( bRemoveAdjCellBorder == rBoxItem.bRemoveAdjCellBorder ) &&
1317         CmpBrdLn( pTop, rBoxItem.GetTop() )           &&
1318         CmpBrdLn( pBottom, rBoxItem.GetBottom() )     &&
1319         CmpBrdLn( pLeft, rBoxItem.GetLeft() )         &&
1320         CmpBrdLn( pRight, rBoxItem.GetRight() ) );
1321 }
1322 
1323 
1324 table::BorderLine2 SvxBoxItem::SvxLineToLine(const SvxBorderLine* pLine, bool bConvert)
1325 {
1326     table::BorderLine2 aLine;
1327     if(pLine)
1328     {
1329         aLine.Color          = sal_Int32(pLine->GetColor());
1330         aLine.InnerLineWidth = sal_uInt16( bConvert ? convertTwipToMm100(pLine->GetInWidth() ): pLine->GetInWidth() );
1331         aLine.OuterLineWidth = sal_uInt16( bConvert ? convertTwipToMm100(pLine->GetOutWidth()): pLine->GetOutWidth() );
1332         aLine.LineDistance   = sal_uInt16( bConvert ? convertTwipToMm100(pLine->GetDistance()): pLine->GetDistance() );
1333         aLine.LineStyle      = sal_Int16(pLine->GetBorderLineStyle());
1334         aLine.LineWidth      = sal_uInt32( bConvert ? convertTwipToMm100( pLine->GetWidth( ) ) : pLine->GetWidth( ) );
1335     }
1336     else
1337         aLine.Color          = aLine.InnerLineWidth = aLine.OuterLineWidth = aLine.LineDistance  = 0;
1338     return aLine;
1339 }
1340 
1341 bool SvxBoxItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
1342 {
1343     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
1344     table::BorderLine2 aRetLine;
1345     sal_uInt16 nDist = 0;
1346     bool bDistMember = false;
1347     nMemberId &= ~CONVERT_TWIPS;
1348     switch(nMemberId)
1349     {
1350         case 0:
1351         {
1352             // 4 Borders and 5 distances
1353             uno::Sequence< uno::Any > aSeq( 9 );
1354             aSeq[0] <<= SvxBoxItem::SvxLineToLine(GetLeft(), bConvert);
1355             aSeq[1] <<= SvxBoxItem::SvxLineToLine(GetRight(), bConvert);
1356             aSeq[2] <<= SvxBoxItem::SvxLineToLine(GetBottom(), bConvert);
1357             aSeq[3] <<= SvxBoxItem::SvxLineToLine(GetTop(), bConvert);
1358             aSeq[4] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( GetSmallestDistance()) : GetSmallestDistance());
1359             aSeq[5] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nTopDist ) : nTopDist );
1360             aSeq[6] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nBottomDist ) : nBottomDist );
1361             aSeq[7] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nLeftDist ) : nLeftDist );
1362             aSeq[8] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100( nRightDist ) : nRightDist );
1363             rVal <<= aSeq;
1364             return true;
1365         }
1366         case MID_LEFT_BORDER:
1367         case LEFT_BORDER:
1368             aRetLine = SvxBoxItem::SvxLineToLine(GetLeft(), bConvert);
1369             break;
1370         case MID_RIGHT_BORDER:
1371         case RIGHT_BORDER:
1372             aRetLine = SvxBoxItem::SvxLineToLine(GetRight(), bConvert);
1373             break;
1374         case MID_BOTTOM_BORDER:
1375         case BOTTOM_BORDER:
1376             aRetLine = SvxBoxItem::SvxLineToLine(GetBottom(), bConvert);
1377             break;
1378         case MID_TOP_BORDER:
1379         case TOP_BORDER:
1380             aRetLine = SvxBoxItem::SvxLineToLine(GetTop(), bConvert);
1381             break;
1382         case BORDER_DISTANCE:
1383             nDist = GetSmallestDistance();
1384             bDistMember = true;
1385             break;
1386         case TOP_BORDER_DISTANCE:
1387             nDist = nTopDist;
1388             bDistMember = true;
1389             break;
1390         case BOTTOM_BORDER_DISTANCE:
1391             nDist = nBottomDist;
1392             bDistMember = true;
1393             break;
1394         case LEFT_BORDER_DISTANCE:
1395             nDist = nLeftDist;
1396             bDistMember = true;
1397             break;
1398         case RIGHT_BORDER_DISTANCE:
1399             nDist = nRightDist;
1400             bDistMember = true;
1401             break;
1402         case LINE_STYLE:
1403         case LINE_WIDTH:
1404             // it doesn't make sense to return a value for these since it's
1405             // probably ambiguous
1406             return true;
1407             break;
1408     }
1409 
1410     if( bDistMember )
1411         rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(nDist) : nDist);
1412     else
1413         rVal <<= aRetLine;
1414 
1415     return true;
1416 }
1417 
1418 namespace
1419 {
1420 
1421 bool
1422 lcl_lineToSvxLine(const table::BorderLine& rLine, SvxBorderLine& rSvxLine, bool bConvert, bool bGuessWidth)
1423 {
1424     rSvxLine.SetColor( Color(rLine.Color));
1425     if ( bGuessWidth )
1426     {
1427         rSvxLine.GuessLinesWidths( rSvxLine.GetBorderLineStyle(),
1428                 sal_uInt16( bConvert ? convertMm100ToTwip(rLine.OuterLineWidth) : rLine.OuterLineWidth  ),
1429                 sal_uInt16( bConvert ? convertMm100ToTwip(rLine.InnerLineWidth) : rLine.InnerLineWidth  ),
1430                 sal_uInt16( bConvert ? convertMm100ToTwip(rLine.LineDistance )  : rLine.LineDistance  ));
1431     }
1432 
1433     bool bRet = !rSvxLine.isEmpty();
1434     return bRet;
1435 }
1436 
1437 }
1438 
1439 
1440 bool SvxBoxItem::LineToSvxLine(const css::table::BorderLine& rLine, SvxBorderLine& rSvxLine, bool bConvert)
1441 {
1442     return lcl_lineToSvxLine(rLine, rSvxLine, bConvert, true);
1443 }
1444 
1445 bool
1446 SvxBoxItem::LineToSvxLine(const css::table::BorderLine2& rLine, SvxBorderLine& rSvxLine, bool bConvert)
1447 {
1448     SvxBorderLineStyle const nStyle =
1449         (rLine.LineStyle < 0 || BORDER_LINE_STYLE_MAX < rLine.LineStyle)
1450         ? SvxBorderLineStyle::SOLID     // default
1451         : static_cast<SvxBorderLineStyle>(rLine.LineStyle);
1452 
1453     rSvxLine.SetBorderLineStyle( nStyle );
1454 
1455     bool bGuessWidth = true;
1456     if ( rLine.LineWidth )
1457     {
1458         rSvxLine.SetWidth( bConvert? convertMm100ToTwip( rLine.LineWidth ) : rLine.LineWidth );
1459         // fdo#46112: double does not necessarily mean symmetric
1460         // for backwards compatibility
1461         bGuessWidth = (SvxBorderLineStyle::DOUBLE == nStyle || SvxBorderLineStyle::DOUBLE_THIN == nStyle) &&
1462             (rLine.InnerLineWidth > 0) && (rLine.OuterLineWidth > 0);
1463     }
1464 
1465     return lcl_lineToSvxLine(rLine, rSvxLine, bConvert, bGuessWidth);
1466 }
1467 
1468 
1469 namespace
1470 {
1471 
1472 bool
1473 lcl_extractBorderLine(const uno::Any& rAny, table::BorderLine2& rLine)
1474 {
1475     if (rAny >>= rLine)
1476         return true;
1477 
1478     table::BorderLine aBorderLine;
1479     if (rAny >>= aBorderLine)
1480     {
1481         rLine.Color = aBorderLine.Color;
1482         rLine.InnerLineWidth = aBorderLine.InnerLineWidth;
1483         rLine.OuterLineWidth = aBorderLine.OuterLineWidth;
1484         rLine.LineDistance = aBorderLine.LineDistance;
1485         rLine.LineStyle = table::BorderLineStyle::SOLID;
1486         return true;
1487     }
1488 
1489     return false;
1490 }
1491 
1492 template<typename Item, typename Line>
1493 bool
1494 lcl_setLine(const uno::Any& rAny, Item& rItem, Line nLine, const bool bConvert)
1495 {
1496     bool bDone = false;
1497     table::BorderLine2 aBorderLine;
1498     if (lcl_extractBorderLine(rAny, aBorderLine))
1499     {
1500         SvxBorderLine aLine;
1501         bool bSet = SvxBoxItem::LineToSvxLine(aBorderLine, aLine, bConvert);
1502         rItem.SetLine( bSet ? &aLine : nullptr, nLine);
1503         bDone = true;
1504     }
1505     return bDone;
1506 }
1507 
1508 }
1509 
1510 bool SvxBoxItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
1511 {
1512     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
1513     SvxBoxItemLine nLine = SvxBoxItemLine::TOP;
1514     bool bDistMember = false;
1515     nMemberId &= ~CONVERT_TWIPS;
1516     switch(nMemberId)
1517     {
1518         case 0:
1519         {
1520             uno::Sequence< uno::Any > aSeq;
1521             if (( rVal >>= aSeq ) && ( aSeq.getLength() == 9 ))
1522             {
1523                 // 4 Borders and 5 distances
1524                 const SvxBoxItemLine aBorders[] = { SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::TOP };
1525                 for (int n(0); n != SAL_N_ELEMENTS(aBorders); ++n)
1526                 {
1527                     if (!lcl_setLine(aSeq[n], *this, aBorders[n], bConvert))
1528                         return false;
1529                 }
1530 
1531                 // WTH are the borders and the distances saved in different order?
1532                 SvxBoxItemLine const nLines[4] = { SvxBoxItemLine::TOP, SvxBoxItemLine::BOTTOM, SvxBoxItemLine::LEFT, SvxBoxItemLine::RIGHT };
1533                 for ( sal_Int32 n = 4; n < 9; n++ )
1534                 {
1535                     sal_Int32 nDist = 0;
1536                     if ( aSeq[n] >>= nDist )
1537                     {
1538                         if( bConvert )
1539                             nDist = convertMm100ToTwip(nDist);
1540                         if ( n == 4 )
1541                             SetAllDistances(sal_uInt16(nDist));
1542                         else
1543                             SetDistance( sal_uInt16( nDist ), nLines[n-5] );
1544                     }
1545                     else
1546                         return false;
1547                 }
1548 
1549                 return true;
1550             }
1551             else
1552                 return false;
1553         }
1554         case LEFT_BORDER_DISTANCE:
1555             bDistMember = true;
1556             [[fallthrough]];
1557         case LEFT_BORDER:
1558         case MID_LEFT_BORDER:
1559             nLine = SvxBoxItemLine::LEFT;
1560             break;
1561         case RIGHT_BORDER_DISTANCE:
1562             bDistMember = true;
1563             [[fallthrough]];
1564         case RIGHT_BORDER:
1565         case MID_RIGHT_BORDER:
1566             nLine = SvxBoxItemLine::RIGHT;
1567             break;
1568         case BOTTOM_BORDER_DISTANCE:
1569             bDistMember = true;
1570             [[fallthrough]];
1571         case BOTTOM_BORDER:
1572         case MID_BOTTOM_BORDER:
1573             nLine = SvxBoxItemLine::BOTTOM;
1574             break;
1575         case TOP_BORDER_DISTANCE:
1576             bDistMember = true;
1577             [[fallthrough]];
1578         case TOP_BORDER:
1579         case MID_TOP_BORDER:
1580             nLine = SvxBoxItemLine::TOP;
1581             break;
1582         case LINE_STYLE:
1583             {
1584                 drawing::LineStyle eDrawingStyle;
1585                 rVal >>= eDrawingStyle;
1586                 SvxBorderLineStyle eBorderStyle = SvxBorderLineStyle::NONE;
1587                 switch ( eDrawingStyle )
1588                 {
1589                     default:
1590                     case drawing::LineStyle_NONE:
1591                         break;
1592                     case drawing::LineStyle_SOLID:
1593                         eBorderStyle = SvxBorderLineStyle::SOLID;
1594                         break;
1595                     case drawing::LineStyle_DASH:
1596                         eBorderStyle = SvxBorderLineStyle::DASHED;
1597                         break;
1598                 }
1599 
1600                 // Set the line style on all borders
1601                 for( SvxBoxItemLine n : o3tl::enumrange<SvxBoxItemLine>() )
1602                 {
1603                     editeng::SvxBorderLine* pLine = const_cast< editeng::SvxBorderLine* >( GetLine( n ) );
1604                     if( pLine )
1605                         pLine->SetBorderLineStyle( eBorderStyle );
1606                 }
1607                 return true;
1608             }
1609             break;
1610         case LINE_WIDTH:
1611             {
1612                 // Set the line width on all borders
1613                 long nWidth(0);
1614                 rVal >>= nWidth;
1615                 if( bConvert )
1616                     nWidth = convertMm100ToTwip( nWidth );
1617 
1618                 // Set the line Width on all borders
1619                 for( SvxBoxItemLine n : o3tl::enumrange<SvxBoxItemLine>() )
1620                 {
1621                     editeng::SvxBorderLine* pLine = const_cast< editeng::SvxBorderLine* >( GetLine( n ) );
1622                     if( pLine )
1623                         pLine->SetWidth( nWidth );
1624                 }
1625             }
1626             return true;
1627     }
1628 
1629     if( bDistMember || nMemberId == BORDER_DISTANCE )
1630     {
1631         sal_Int32 nDist = 0;
1632         if(!(rVal >>= nDist))
1633             return false;
1634 
1635         if(nDist >= 0)
1636         {
1637             if( bConvert )
1638                 nDist = convertMm100ToTwip(nDist);
1639             if( nMemberId == BORDER_DISTANCE )
1640                 SetAllDistances(sal_uInt16(nDist));
1641             else
1642                 SetDistance( sal_uInt16( nDist ), nLine );
1643         }
1644     }
1645     else
1646     {
1647         SvxBorderLine aLine;
1648         if( !rVal.hasValue() )
1649             return false;
1650 
1651         table::BorderLine2 aBorderLine;
1652         if( lcl_extractBorderLine(rVal, aBorderLine) )
1653         {
1654             // usual struct
1655         }
1656         else if (rVal.getValueTypeClass() == uno::TypeClass_SEQUENCE )
1657         {
1658             // serialization for basic macro recording
1659             uno::Reference < script::XTypeConverter > xConverter
1660                     ( script::Converter::create(::comphelper::getProcessComponentContext()) );
1661             uno::Sequence < uno::Any > aSeq;
1662             uno::Any aNew;
1663             try { aNew = xConverter->convertTo( rVal, cppu::UnoType<uno::Sequence < uno::Any >>::get() ); }
1664             catch (const uno::Exception&) {}
1665 
1666             aNew >>= aSeq;
1667             if (aSeq.getLength() >= 4 && aSeq.getLength() <= 6)
1668             {
1669                 sal_Int32 nVal = 0;
1670                 if ( aSeq[0] >>= nVal )
1671                     aBorderLine.Color = nVal;
1672                 if ( aSeq[1] >>= nVal )
1673                     aBorderLine.InnerLineWidth = static_cast<sal_Int16>(nVal);
1674                 if ( aSeq[2] >>= nVal )
1675                     aBorderLine.OuterLineWidth = static_cast<sal_Int16>(nVal);
1676                 if ( aSeq[3] >>= nVal )
1677                     aBorderLine.LineDistance = static_cast<sal_Int16>(nVal);
1678                 if (aSeq.getLength() >= 5) // fdo#40874 added fields
1679                 {
1680                     if (aSeq[4] >>= nVal)
1681                     {
1682                         aBorderLine.LineStyle = nVal;
1683                     }
1684                     if (aSeq.getLength() >= 6)
1685                     {
1686                         if (aSeq[5] >>= nVal)
1687                         {
1688                             aBorderLine.LineWidth = nVal;
1689                         }
1690                     }
1691                 }
1692             }
1693             else
1694                 return false;
1695         }
1696         else
1697             return false;
1698 
1699         bool bSet = SvxBoxItem::LineToSvxLine(aBorderLine, aLine, bConvert);
1700         SetLine(bSet ? &aLine : nullptr, nLine);
1701     }
1702 
1703     return true;
1704 }
1705 
1706 SvxBoxItem* SvxBoxItem::Clone( SfxItemPool* ) const
1707 {
1708     return new SvxBoxItem( *this );
1709 }
1710 
1711 bool SvxBoxItem::GetPresentation
1712 (
1713     SfxItemPresentation ePres,
1714     MapUnit             eCoreUnit,
1715     MapUnit             ePresUnit,
1716     OUString&           rText, const IntlWrapper& rIntl
1717 )   const
1718 {
1719     OUString cpDelimTmp(cpDelim);
1720     switch ( ePres )
1721     {
1722         case SfxItemPresentation::Nameless:
1723         {
1724             rText.clear();
1725 
1726             if ( pTop )
1727             {
1728                 rText = pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp;
1729             }
1730             if( !(pTop && pBottom && pLeft && pRight &&
1731                   *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight) )
1732             {
1733                 if ( pBottom )
1734                 {
1735                     rText += pBottom->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp;
1736                 }
1737                 if ( pLeft )
1738                 {
1739                     rText += pLeft->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp;
1740                 }
1741                 if ( pRight )
1742                 {
1743                     rText += pRight->GetValueString( eCoreUnit, ePresUnit, &rIntl ) + cpDelimTmp;
1744                 }
1745             }
1746             rText += GetMetricText( static_cast<long>(nTopDist), eCoreUnit, ePresUnit, &rIntl );
1747             if( nTopDist != nBottomDist || nTopDist != nLeftDist ||
1748                 nTopDist != nRightDist )
1749             {
1750                 rText += cpDelimTmp +
1751                         GetMetricText( static_cast<long>(nBottomDist), eCoreUnit,
1752                                         ePresUnit, &rIntl ) +
1753                         cpDelimTmp +
1754                         GetMetricText( static_cast<long>(nLeftDist), eCoreUnit, ePresUnit, &rIntl ) +
1755                         cpDelimTmp +
1756                         GetMetricText( static_cast<long>(nRightDist), eCoreUnit,
1757                                         ePresUnit, &rIntl );
1758             }
1759             return true;
1760         }
1761         case SfxItemPresentation::Complete:
1762         {
1763             if( !(pTop || pBottom || pLeft || pRight) )
1764             {
1765                 rText = EditResId(RID_SVXITEMS_BORDER_NONE) + cpDelimTmp;
1766             }
1767             else
1768             {
1769                 rText = EditResId(RID_SVXITEMS_BORDER_COMPLETE);
1770                 if( pTop && pBottom && pLeft && pRight &&
1771                     *pTop == *pBottom && *pTop == *pLeft && *pTop == *pRight )
1772                 {
1773                     rText += pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) + cpDelimTmp;
1774                 }
1775                 else
1776                 {
1777                     if ( pTop )
1778                     {
1779                         rText += EditResId(RID_SVXITEMS_BORDER_TOP) +
1780                                 pTop->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) +
1781                                 cpDelimTmp;
1782                     }
1783                     if ( pBottom )
1784                     {
1785                         rText += EditResId(RID_SVXITEMS_BORDER_BOTTOM) +
1786                                 pBottom->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) +
1787                                 cpDelimTmp;
1788                     }
1789                     if ( pLeft )
1790                     {
1791                         rText += EditResId(RID_SVXITEMS_BORDER_LEFT) +
1792                                 pLeft->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) +
1793                                 cpDelimTmp;
1794                     }
1795                     if ( pRight )
1796                     {
1797                         rText += EditResId(RID_SVXITEMS_BORDER_RIGHT) +
1798                                 pRight->GetValueString( eCoreUnit, ePresUnit, &rIntl, true ) +
1799                                 cpDelimTmp;
1800                     }
1801                 }
1802             }
1803 
1804             rText += EditResId(RID_SVXITEMS_BORDER_DISTANCE);
1805             if( nTopDist == nBottomDist && nTopDist == nLeftDist &&
1806                 nTopDist == nRightDist )
1807             {
1808                 rText += GetMetricText( static_cast<long>(nTopDist), eCoreUnit,
1809                                             ePresUnit, &rIntl ) +
1810                         " " + EditResId(GetMetricId(ePresUnit));
1811             }
1812             else
1813             {
1814                 rText += EditResId(RID_SVXITEMS_BORDER_TOP) +
1815                         GetMetricText( static_cast<long>(nTopDist), eCoreUnit,
1816                                         ePresUnit, &rIntl ) +
1817                         " " + EditResId(GetMetricId(ePresUnit)) +
1818                         cpDelimTmp +
1819                         EditResId(RID_SVXITEMS_BORDER_BOTTOM) +
1820                         GetMetricText( static_cast<long>(nBottomDist), eCoreUnit,
1821                                         ePresUnit, &rIntl ) +
1822                         " " + EditResId(GetMetricId(ePresUnit)) +
1823                         cpDelimTmp +
1824                         EditResId(RID_SVXITEMS_BORDER_LEFT) +
1825                         GetMetricText( static_cast<long>(nLeftDist), eCoreUnit,
1826                                         ePresUnit, &rIntl ) +
1827                         " " + EditResId(GetMetricId(ePresUnit)) +
1828                         cpDelimTmp +
1829                         EditResId(RID_SVXITEMS_BORDER_RIGHT) +
1830                         GetMetricText( static_cast<long>(nRightDist), eCoreUnit,
1831                                         ePresUnit, &rIntl ) +
1832                         " " + EditResId(GetMetricId(ePresUnit));
1833             }
1834             return true;
1835         }
1836         default: ; // prevent warning
1837     }
1838     return false;
1839 }
1840 
1841 
1842 void SvxBoxItem::ScaleMetrics( long nMult, long nDiv )
1843 {
1844     if ( pTop )     pTop->ScaleMetrics( nMult, nDiv );
1845     if ( pBottom )  pBottom->ScaleMetrics( nMult, nDiv );
1846     if ( pLeft )    pLeft->ScaleMetrics( nMult, nDiv );
1847     if ( pRight )   pRight->ScaleMetrics( nMult, nDiv );
1848     nTopDist = static_cast<sal_uInt16>(Scale( nTopDist, nMult, nDiv ));
1849     nBottomDist = static_cast<sal_uInt16>(Scale( nBottomDist, nMult, nDiv ));
1850     nLeftDist = static_cast<sal_uInt16>(Scale( nLeftDist, nMult, nDiv ));
1851     nRightDist = static_cast<sal_uInt16>(Scale( nRightDist, nMult, nDiv ));
1852 }
1853 
1854 
1855 bool SvxBoxItem::HasMetrics() const
1856 {
1857     return true;
1858 }
1859 
1860 
1861 const SvxBorderLine *SvxBoxItem::GetLine( SvxBoxItemLine nLine ) const
1862 {
1863     const SvxBorderLine *pRet = nullptr;
1864 
1865     switch ( nLine )
1866     {
1867         case SvxBoxItemLine::TOP:
1868             pRet = pTop.get();
1869             break;
1870         case SvxBoxItemLine::BOTTOM:
1871             pRet = pBottom.get();
1872             break;
1873         case SvxBoxItemLine::LEFT:
1874             pRet = pLeft.get();
1875             break;
1876         case SvxBoxItemLine::RIGHT:
1877             pRet = pRight.get();
1878             break;
1879         default:
1880             OSL_FAIL( "wrong line" );
1881             break;
1882     }
1883 
1884     return pRet;
1885 }
1886 
1887 
1888 void SvxBoxItem::SetLine( const SvxBorderLine* pNew, SvxBoxItemLine nLine )
1889 {
1890     std::unique_ptr<SvxBorderLine> pTmp( pNew ? new SvxBorderLine( *pNew ) : nullptr );
1891 
1892     switch ( nLine )
1893     {
1894         case SvxBoxItemLine::TOP:
1895             pTop = std::move( pTmp );
1896             break;
1897         case SvxBoxItemLine::BOTTOM:
1898             pBottom = std::move( pTmp );
1899             break;
1900         case SvxBoxItemLine::LEFT:
1901             pLeft = std::move( pTmp );
1902             break;
1903         case SvxBoxItemLine::RIGHT:
1904             pRight = std::move( pTmp );
1905             break;
1906         default:
1907             OSL_FAIL( "wrong line" );
1908     }
1909 }
1910 
1911 
1912 sal_uInt16 SvxBoxItem::GetSmallestDistance() const
1913 {
1914     // The smallest distance that is not 0 will be returned.
1915     sal_uInt16 nDist = nTopDist;
1916     if( nBottomDist && (!nDist || nBottomDist < nDist) )
1917         nDist = nBottomDist;
1918     if( nLeftDist && (!nDist || nLeftDist < nDist) )
1919         nDist = nLeftDist;
1920     if( nRightDist && (!nDist || nRightDist < nDist) )
1921         nDist = nRightDist;
1922 
1923     return nDist;
1924 }
1925 
1926 
1927 sal_uInt16 SvxBoxItem::GetDistance( SvxBoxItemLine nLine ) const
1928 {
1929     sal_uInt16 nDist = 0;
1930     switch ( nLine )
1931     {
1932         case SvxBoxItemLine::TOP:
1933             nDist = nTopDist;
1934             break;
1935         case SvxBoxItemLine::BOTTOM:
1936             nDist = nBottomDist;
1937             break;
1938         case SvxBoxItemLine::LEFT:
1939             nDist = nLeftDist;
1940             break;
1941         case SvxBoxItemLine::RIGHT:
1942             nDist = nRightDist;
1943             break;
1944         default:
1945             OSL_FAIL( "wrong line" );
1946     }
1947 
1948     return nDist;
1949 }
1950 
1951 
1952 void SvxBoxItem::SetDistance( sal_uInt16 nNew, SvxBoxItemLine nLine )
1953 {
1954     switch ( nLine )
1955     {
1956         case SvxBoxItemLine::TOP:
1957             nTopDist = nNew;
1958             break;
1959         case SvxBoxItemLine::BOTTOM:
1960             nBottomDist = nNew;
1961             break;
1962         case SvxBoxItemLine::LEFT:
1963             nLeftDist = nNew;
1964             break;
1965         case SvxBoxItemLine::RIGHT:
1966             nRightDist = nNew;
1967             break;
1968         default:
1969             OSL_FAIL( "wrong line" );
1970     }
1971 }
1972 
1973 sal_uInt16 SvxBoxItem::CalcLineWidth( SvxBoxItemLine nLine ) const
1974 {
1975     SvxBorderLine* pTmp = nullptr;
1976     sal_uInt16 nWidth = 0;
1977     switch ( nLine )
1978     {
1979     case SvxBoxItemLine::TOP:
1980         pTmp = pTop.get();
1981         break;
1982     case SvxBoxItemLine::BOTTOM:
1983         pTmp = pBottom.get();
1984         break;
1985     case SvxBoxItemLine::LEFT:
1986         pTmp = pLeft.get();
1987         break;
1988     case SvxBoxItemLine::RIGHT:
1989         pTmp = pRight.get();
1990         break;
1991     default:
1992         OSL_FAIL( "wrong line" );
1993     }
1994 
1995     if( pTmp )
1996         nWidth = pTmp->GetScaledWidth();
1997 
1998     return nWidth;
1999 }
2000 
2001 sal_uInt16 SvxBoxItem::CalcLineSpace( SvxBoxItemLine nLine, bool bEvenIfNoLine ) const
2002 {
2003     SvxBorderLine* pTmp = nullptr;
2004     sal_uInt16 nDist = 0;
2005     switch ( nLine )
2006     {
2007     case SvxBoxItemLine::TOP:
2008         pTmp = pTop.get();
2009         nDist = nTopDist;
2010         break;
2011     case SvxBoxItemLine::BOTTOM:
2012         pTmp = pBottom.get();
2013         nDist = nBottomDist;
2014         break;
2015     case SvxBoxItemLine::LEFT:
2016         pTmp = pLeft.get();
2017         nDist = nLeftDist;
2018         break;
2019     case SvxBoxItemLine::RIGHT:
2020         pTmp = pRight.get();
2021         nDist = nRightDist;
2022         break;
2023     default:
2024         OSL_FAIL( "wrong line" );
2025     }
2026 
2027     if( pTmp )
2028     {
2029         nDist = nDist + pTmp->GetScaledWidth();
2030     }
2031     else if( !bEvenIfNoLine )
2032         nDist = 0;
2033     return nDist;
2034 }
2035 
2036 bool SvxBoxItem::HasBorder( bool bTreatPaddingAsBorder ) const
2037 {
2038     return  CalcLineSpace( SvxBoxItemLine::BOTTOM,   bTreatPaddingAsBorder )
2039             || CalcLineSpace( SvxBoxItemLine::RIGHT, bTreatPaddingAsBorder )
2040             || CalcLineSpace( SvxBoxItemLine::TOP,   bTreatPaddingAsBorder )
2041             || CalcLineSpace( SvxBoxItemLine::LEFT,  bTreatPaddingAsBorder );
2042 }
2043 
2044 // class SvxBoxInfoItem --------------------------------------------------
2045 
2046 SvxBoxInfoItem::SvxBoxInfoItem( const sal_uInt16 nId ) :
2047     SfxPoolItem( nId ),
2048     mbEnableHor( false ),
2049     mbEnableVer( false ),
2050     nDefDist( 0 )
2051 {
2052     bDist = bMinDist = false;
2053     ResetFlags();
2054 }
2055 
2056 
2057 SvxBoxInfoItem::SvxBoxInfoItem( const SvxBoxInfoItem& rCpy ) :
2058     SfxPoolItem( rCpy ),
2059     pHori( rCpy.pHori ? new SvxBorderLine( *rCpy.pHori ) : nullptr ),
2060     pVert( rCpy.pVert ? new SvxBorderLine( *rCpy.pVert ) : nullptr ),
2061     mbEnableHor( rCpy.mbEnableHor ),
2062     mbEnableVer( rCpy.mbEnableVer ),
2063     bDist( rCpy.bDist ),
2064     bMinDist ( rCpy.bMinDist ),
2065     nValidFlags( rCpy.nValidFlags ),
2066     nDefDist( rCpy.nDefDist )
2067 {
2068 }
2069 
2070 SvxBoxInfoItem::~SvxBoxInfoItem()
2071 {
2072 }
2073 
2074 bool SvxBoxInfoItem::operator==( const SfxPoolItem& rAttr ) const
2075 {
2076     assert(SfxPoolItem::operator==(rAttr));
2077 
2078     const SvxBoxInfoItem& rBoxInfo = static_cast<const SvxBoxInfoItem&>(rAttr);
2079 
2080     return (   mbEnableHor               == rBoxInfo.mbEnableHor
2081             && mbEnableVer               == rBoxInfo.mbEnableVer
2082             && bDist                     == rBoxInfo.IsDist()
2083             && bMinDist                  == rBoxInfo.IsMinDist()
2084             && nValidFlags               == rBoxInfo.nValidFlags
2085             && nDefDist                  == rBoxInfo.GetDefDist()
2086             && CmpBrdLn( pHori, rBoxInfo.GetHori() )
2087             && CmpBrdLn( pVert, rBoxInfo.GetVert() )
2088            );
2089 }
2090 
2091 
2092 void SvxBoxInfoItem::SetLine( const SvxBorderLine* pNew, SvxBoxInfoItemLine nLine )
2093 {
2094     std::unique_ptr<SvxBorderLine> pTmp( pNew ? new SvxBorderLine( *pNew ) : nullptr );
2095 
2096     if ( SvxBoxInfoItemLine::HORI == nLine )
2097     {
2098         pHori = std::move(pTmp);
2099     }
2100     else if ( SvxBoxInfoItemLine::VERT == nLine )
2101     {
2102         pVert = std::move(pTmp);
2103     }
2104     else
2105     {
2106         OSL_FAIL( "wrong line" );
2107     }
2108 }
2109 
2110 SvxBoxInfoItem* SvxBoxInfoItem::Clone( SfxItemPool* ) const
2111 {
2112     return new SvxBoxInfoItem( *this );
2113 }
2114 
2115 bool SvxBoxInfoItem::GetPresentation
2116 (
2117     SfxItemPresentation /*ePres*/,
2118     MapUnit             /*eCoreUnit*/,
2119     MapUnit             /*ePresUnit*/,
2120     OUString&           rText, const IntlWrapper&
2121 )   const
2122 {
2123     rText.clear();
2124     return false;
2125 }
2126 
2127 
2128 void SvxBoxInfoItem::ScaleMetrics( long nMult, long nDiv )
2129 {
2130     if ( pHori ) pHori->ScaleMetrics( nMult, nDiv );
2131     if ( pVert ) pVert->ScaleMetrics( nMult, nDiv );
2132     nDefDist = static_cast<sal_uInt16>(Scale( nDefDist, nMult, nDiv ));
2133 }
2134 
2135 
2136 bool SvxBoxInfoItem::HasMetrics() const
2137 {
2138     return true;
2139 }
2140 
2141 
2142 void SvxBoxInfoItem::ResetFlags()
2143 {
2144     nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(0x7F); // all valid except Disable
2145 }
2146 
2147 bool SvxBoxInfoItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
2148 {
2149     bool bConvert = 0 != (nMemberId & CONVERT_TWIPS);
2150     table::BorderLine2 aRetLine;
2151     sal_Int16 nVal=0;
2152     bool bIntMember = false;
2153     nMemberId &= ~CONVERT_TWIPS;
2154     switch(nMemberId)
2155     {
2156         case 0:
2157         {
2158             // 2 BorderLines, flags, valid flags and distance
2159             css::uno::Sequence< css::uno::Any > aSeq( 5 );
2160             aSeq[0] <<= SvxBoxItem::SvxLineToLine( pHori.get(), bConvert);
2161             aSeq[1] <<= SvxBoxItem::SvxLineToLine( pVert.get(), bConvert);
2162             if ( IsTable() )
2163                 nVal |= 0x01;
2164             if ( IsDist() )
2165                 nVal |= 0x02;
2166             if ( IsMinDist() )
2167                 nVal |= 0x04;
2168             aSeq[2] <<= nVal;
2169             aSeq[3] <<= static_cast<sal_Int16>(nValidFlags);
2170             aSeq[4] <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetDefDist()) : GetDefDist());
2171             rVal <<= aSeq;
2172             return true;
2173         }
2174 
2175         case MID_HORIZONTAL:
2176             aRetLine = SvxBoxItem::SvxLineToLine( pHori.get(), bConvert);
2177             break;
2178         case MID_VERTICAL:
2179             aRetLine = SvxBoxItem::SvxLineToLine( pVert.get(), bConvert);
2180             break;
2181         case MID_FLAGS:
2182             bIntMember = true;
2183             if ( IsTable() )
2184                 nVal |= 0x01;
2185             if ( IsDist() )
2186                 nVal |= 0x02;
2187             if ( IsMinDist() )
2188                 nVal |= 0x04;
2189             rVal <<= nVal;
2190             break;
2191         case MID_VALIDFLAGS:
2192             bIntMember = true;
2193             rVal <<= static_cast<sal_Int16>(nValidFlags);
2194             break;
2195         case MID_DISTANCE:
2196             bIntMember = true;
2197             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(GetDefDist()) : GetDefDist());
2198             break;
2199         default: OSL_FAIL("Wrong MemberId!"); return false;
2200     }
2201 
2202     if( !bIntMember )
2203         rVal <<= aRetLine;
2204 
2205     return true;
2206 }
2207 
2208 
2209 bool SvxBoxInfoItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
2210 {
2211     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
2212     nMemberId &= ~CONVERT_TWIPS;
2213     bool bRet;
2214     switch(nMemberId)
2215     {
2216         case 0:
2217         {
2218             css::uno::Sequence< css::uno::Any > aSeq;
2219             if (( rVal >>= aSeq ) && ( aSeq.getLength() == 5 ))
2220             {
2221                 // 2 BorderLines, flags, valid flags and distance
2222                 if (!lcl_setLine(aSeq[0], *this, SvxBoxInfoItemLine::HORI, bConvert))
2223                     return false;
2224                 if (!lcl_setLine(aSeq[1], *this, SvxBoxInfoItemLine::VERT, bConvert))
2225                     return false;
2226 
2227                 sal_Int16 nFlags( 0 );
2228                 sal_Int32 nVal( 0 );
2229                 if ( aSeq[2] >>= nFlags )
2230                 {
2231                     SetTable  ( ( nFlags & 0x01 ) != 0 );
2232                     SetDist   ( ( nFlags & 0x02 ) != 0 );
2233                     SetMinDist( ( nFlags & 0x04 ) != 0 );
2234                 }
2235                 else
2236                     return false;
2237                 if ( aSeq[3] >>= nFlags )
2238                     nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags);
2239                 else
2240                     return false;
2241                 if (( aSeq[4] >>= nVal ) && ( nVal >= 0 ))
2242                 {
2243                     if( bConvert )
2244                         nVal = convertMm100ToTwip(nVal);
2245                     SetDefDist( static_cast<sal_uInt16>(nVal) );
2246                 }
2247             }
2248             return true;
2249         }
2250 
2251         case MID_HORIZONTAL:
2252         case MID_VERTICAL:
2253         {
2254             if( !rVal.hasValue() )
2255                 return false;
2256 
2257             table::BorderLine2 aBorderLine;
2258             if( lcl_extractBorderLine(rVal, aBorderLine) )
2259             {
2260                 // usual struct
2261             }
2262             else if (rVal.getValueTypeClass() == uno::TypeClass_SEQUENCE )
2263             {
2264                 // serialization for basic macro recording
2265                 uno::Reference < script::XTypeConverter > xConverter( script::Converter::create(::comphelper::getProcessComponentContext()) );
2266                 uno::Any aNew;
2267                 uno::Sequence < uno::Any > aSeq;
2268                 try { aNew = xConverter->convertTo( rVal, cppu::UnoType<uno::Sequence < uno::Any >>::get() ); }
2269                 catch (const uno::Exception&) {}
2270 
2271                 if ((aNew >>= aSeq) &&
2272                     aSeq.getLength() >= 4  && aSeq.getLength() <= 6)
2273                 {
2274                     sal_Int32 nVal = 0;
2275                     if ( aSeq[0] >>= nVal )
2276                         aBorderLine.Color = nVal;
2277                     if ( aSeq[1] >>= nVal )
2278                         aBorderLine.InnerLineWidth = static_cast<sal_Int16>(nVal);
2279                     if ( aSeq[2] >>= nVal )
2280                         aBorderLine.OuterLineWidth = static_cast<sal_Int16>(nVal);
2281                     if ( aSeq[3] >>= nVal )
2282                         aBorderLine.LineDistance = static_cast<sal_Int16>(nVal);
2283                     if (aSeq.getLength() >= 5) // fdo#40874 added fields
2284                     {
2285                         if (aSeq[4] >>= nVal)
2286                         {
2287                             aBorderLine.LineStyle = nVal;
2288                         }
2289                         if (aSeq.getLength() >= 6)
2290                         {
2291                             if (aSeq[5] >>= nVal)
2292                             {
2293                                 aBorderLine.LineWidth = nVal;
2294                             }
2295                         }
2296                     }
2297                 }
2298                 else
2299                     return false;
2300             }
2301             else if (rVal.getValueType() == cppu::UnoType<css::uno::Sequence < sal_Int16 >>::get() )
2302             {
2303                 // serialization for basic macro recording
2304                 css::uno::Sequence < sal_Int16 > aSeq;
2305                 rVal >>= aSeq;
2306                 if (aSeq.getLength() >= 4 && aSeq.getLength() <= 6)
2307                 {
2308                     aBorderLine.Color = aSeq[0];
2309                     aBorderLine.InnerLineWidth = aSeq[1];
2310                     aBorderLine.OuterLineWidth = aSeq[2];
2311                     aBorderLine.LineDistance = aSeq[3];
2312                     if (aSeq.getLength() >= 5) // fdo#40874 added fields
2313                     {
2314                         aBorderLine.LineStyle = aSeq[4];
2315                         if (aSeq.getLength() >= 6)
2316                         {
2317                             aBorderLine.LineWidth = aSeq[5];
2318                         }
2319                     }
2320                 }
2321                 else
2322                     return false;
2323             }
2324             else
2325                 return false;
2326 
2327             SvxBorderLine aLine;
2328             bool bSet = SvxBoxItem::LineToSvxLine(aBorderLine, aLine, bConvert);
2329             if ( bSet )
2330                 SetLine( &aLine, nMemberId == MID_HORIZONTAL ? SvxBoxInfoItemLine::HORI : SvxBoxInfoItemLine::VERT );
2331             break;
2332         }
2333         case MID_FLAGS:
2334         {
2335             sal_Int16 nFlags = sal_Int16();
2336             bRet = (rVal >>= nFlags);
2337             if ( bRet )
2338             {
2339                 SetTable  ( ( nFlags & 0x01 ) != 0 );
2340                 SetDist   ( ( nFlags & 0x02 ) != 0 );
2341                 SetMinDist( ( nFlags & 0x04 ) != 0 );
2342             }
2343 
2344             break;
2345         }
2346         case MID_VALIDFLAGS:
2347         {
2348             sal_Int16 nFlags = sal_Int16();
2349             bRet = (rVal >>= nFlags);
2350             if ( bRet )
2351                 nValidFlags = static_cast<SvxBoxInfoItemValidFlags>(nFlags);
2352             break;
2353         }
2354         case MID_DISTANCE:
2355         {
2356             sal_Int32 nVal = 0;
2357             bRet = (rVal >>= nVal);
2358             if ( bRet && nVal>=0 )
2359             {
2360                 if( bConvert )
2361                     nVal = convertMm100ToTwip(nVal);
2362                 SetDefDist( static_cast<sal_uInt16>(nVal) );
2363             }
2364             break;
2365         }
2366         default: OSL_FAIL("Wrong MemberId!"); return false;
2367     }
2368 
2369     return true;
2370 }
2371 
2372 
2373 namespace editeng
2374 {
2375 
2376 void BorderDistanceFromWord(bool bFromEdge, sal_Int32& nMargin, sal_Int32& nBorderDistance,
2377     sal_Int32 nBorderWidth)
2378 {
2379     // See https://wiki.openoffice.org/wiki/Writer/MSInteroperability/PageBorder
2380 
2381     sal_Int32 nNewMargin = nMargin;
2382     sal_Int32 nNewBorderDistance = nBorderDistance;
2383 
2384     if (bFromEdge)
2385     {
2386         nNewMargin = nBorderDistance;
2387         nNewBorderDistance = nMargin - nBorderDistance - nBorderWidth;
2388     }
2389     else
2390     {
2391         nNewMargin -= nBorderDistance + nBorderWidth;
2392     }
2393 
2394     // Ensure correct distance from page edge to text in cases not supported by us:
2395     // when border is outside entire page area (!bFromEdge && BorderDistance > Margin),
2396     // and when border is inside page body area (bFromEdge && BorderDistance > Margin)
2397     if (nNewMargin < 0)
2398     {
2399         nNewMargin = 0;
2400         nNewBorderDistance = std::max<sal_Int32>(nMargin - nBorderWidth, 0);
2401     }
2402     else if (nNewBorderDistance < 0)
2403     {
2404         nNewMargin = std::max<sal_Int32>(nMargin - nBorderWidth, 0);
2405         nNewBorderDistance = 0;
2406     }
2407 
2408     nMargin = nNewMargin;
2409     nBorderDistance = nNewBorderDistance;
2410 }
2411 
2412 // Heuristics to decide if we need to use "from edge" offset of borders
2413 //
2414 // There are two cases when we can safely use "from text" or "from edge" offset without distorting
2415 // border position (modulo rounding errors):
2416 // 1. When distance of all borders from text is no greater than 31 pt, we use "from text"
2417 // 2. Otherwise, if distance of all borders from edge is no greater than 31 pt, we use "from edge"
2418 // In all other cases, the position of borders would be distorted on export, because Word doesn't
2419 // support the offset of >31 pts (https://msdn.microsoft.com/en-us/library/ff533820), and we need
2420 // to decide which type of offset would provide less wrong result (i.e., the result would look
2421 // closer to original). Here, we just check sum of distances from text to borders, and if it is
2422 // less than sum of distances from borders to edges. The alternative would be to compare total areas
2423 // between text-and-borders and between borders-and-edges (taking into account different lengths of
2424 // borders, and visual impact of that).
2425 void BorderDistancesToWord(const SvxBoxItem& rBox, const WordPageMargins& rMargins,
2426     WordBorderDistances& rDistances)
2427 {
2428     // Use signed sal_Int32 that can hold sal_uInt16, to prevent overflow at subtraction below
2429     const sal_Int32 nT = rBox.GetDistance(SvxBoxItemLine::TOP);
2430     const sal_Int32 nL = rBox.GetDistance(SvxBoxItemLine::LEFT);
2431     const sal_Int32 nB = rBox.GetDistance(SvxBoxItemLine::BOTTOM);
2432     const sal_Int32 nR = rBox.GetDistance(SvxBoxItemLine::RIGHT);
2433 
2434     // Only take into account existing borders
2435     const SvxBorderLine* pLnT = rBox.GetLine(SvxBoxItemLine::TOP);
2436     const SvxBorderLine* pLnL = rBox.GetLine(SvxBoxItemLine::LEFT);
2437     const SvxBorderLine* pLnB = rBox.GetLine(SvxBoxItemLine::BOTTOM);
2438     const SvxBorderLine* pLnR = rBox.GetLine(SvxBoxItemLine::RIGHT);
2439 
2440     // We need to take border widths into account
2441     const long nWidthT = pLnT ? pLnT->GetScaledWidth() : 0;
2442     const long nWidthL = pLnL ? pLnL->GetScaledWidth() : 0;
2443     const long nWidthB = pLnB ? pLnB->GetScaledWidth() : 0;
2444     const long nWidthR = pLnR ? pLnR->GetScaledWidth() : 0;
2445 
2446     // Resulting distances from text to borders
2447     const sal_Int32 nT2BT = pLnT ? nT : 0;
2448     const sal_Int32 nT2BL = pLnL ? nL : 0;
2449     const sal_Int32 nT2BB = pLnB ? nB : 0;
2450     const sal_Int32 nT2BR = pLnR ? nR : 0;
2451 
2452     // Resulting distances from edge to borders
2453     const sal_Int32 nE2BT = pLnT ? std::max<sal_Int32>(rMargins.nTop - nT - nWidthT, 0) : 0;
2454     const sal_Int32 nE2BL = pLnL ? std::max<sal_Int32>(rMargins.nLeft - nL - nWidthL, 0) : 0;
2455     const sal_Int32 nE2BB = pLnB ? std::max<sal_Int32>(rMargins.nBottom - nB - nWidthB, 0) : 0;
2456     const sal_Int32 nE2BR = pLnR ? std::max<sal_Int32>(rMargins.nRight - nR - nWidthR, 0) : 0;
2457 
2458     const sal_Int32 n32pt = 32 * 20;
2459     // 1. If all borders are in range of 31 pts from text
2460     if (nT2BT < n32pt && nT2BL < n32pt && nT2BB < n32pt && nT2BR < n32pt)
2461     {
2462         rDistances.bFromEdge = false;
2463     }
2464     else
2465     {
2466         // 2. If all borders are in range of 31 pts from edge
2467         if (nE2BT < n32pt && nE2BL < n32pt && nE2BB < n32pt && nE2BR < n32pt)
2468         {
2469             rDistances.bFromEdge = true;
2470         }
2471         else
2472         {
2473             // Let's try to guess which would be the best approximation
2474             rDistances.bFromEdge =
2475                 (nT2BT + nT2BL + nT2BB + nT2BR) > (nE2BT + nE2BL + nE2BB + nE2BR);
2476         }
2477     }
2478 
2479     if (rDistances.bFromEdge)
2480     {
2481         rDistances.nTop = sal::static_int_cast<sal_uInt16>(nE2BT);
2482         rDistances.nLeft = sal::static_int_cast<sal_uInt16>(nE2BL);
2483         rDistances.nBottom = sal::static_int_cast<sal_uInt16>(nE2BB);
2484         rDistances.nRight = sal::static_int_cast<sal_uInt16>(nE2BR);
2485     }
2486     else
2487     {
2488         rDistances.nTop = sal::static_int_cast<sal_uInt16>(nT2BT);
2489         rDistances.nLeft = sal::static_int_cast<sal_uInt16>(nT2BL);
2490         rDistances.nBottom = sal::static_int_cast<sal_uInt16>(nT2BB);
2491         rDistances.nRight = sal::static_int_cast<sal_uInt16>(nT2BR);
2492     }
2493 }
2494 
2495 }
2496 
2497 // class SvxFormatBreakItem -------------------------------------------------
2498 
2499 bool SvxFormatBreakItem::operator==( const SfxPoolItem& rAttr ) const
2500 {
2501     assert(SfxPoolItem::operator==(rAttr));
2502 
2503     return GetValue() == static_cast<const SvxFormatBreakItem&>( rAttr ).GetValue();
2504 }
2505 
2506 
2507 bool SvxFormatBreakItem::GetPresentation
2508 (
2509     SfxItemPresentation /*ePres*/,
2510     MapUnit             /*eCoreUnit*/,
2511     MapUnit             /*ePresUnit*/,
2512     OUString&           rText, const IntlWrapper&
2513 )   const
2514 {
2515     rText = GetValueTextByPos( GetEnumValue() );
2516     return true;
2517 }
2518 
2519 OUString SvxFormatBreakItem::GetValueTextByPos( sal_uInt16 nPos )
2520 {
2521     static const char* RID_SVXITEMS_BREAK[] =
2522     {
2523         RID_SVXITEMS_BREAK_NONE,
2524         RID_SVXITEMS_BREAK_COLUMN_BEFORE,
2525         RID_SVXITEMS_BREAK_COLUMN_AFTER,
2526         RID_SVXITEMS_BREAK_COLUMN_BOTH,
2527         RID_SVXITEMS_BREAK_PAGE_BEFORE,
2528         RID_SVXITEMS_BREAK_PAGE_AFTER,
2529         RID_SVXITEMS_BREAK_PAGE_BOTH
2530     };
2531     static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_BREAK) == size_t(SvxBreak::End), "unexpected size");
2532     assert(nPos < sal_uInt16(SvxBreak::End) && "enum overflow!");
2533     return EditResId(RID_SVXITEMS_BREAK[nPos]);
2534 }
2535 
2536 bool SvxFormatBreakItem::QueryValue( uno::Any& rVal, sal_uInt8 /*nMemberId*/ ) const
2537 {
2538     style::BreakType eBreak = style::BreakType_NONE;
2539     switch ( GetBreak() )
2540     {
2541         case SvxBreak::ColumnBefore:   eBreak = style::BreakType_COLUMN_BEFORE; break;
2542         case SvxBreak::ColumnAfter:    eBreak = style::BreakType_COLUMN_AFTER ; break;
2543         case SvxBreak::ColumnBoth:     eBreak = style::BreakType_COLUMN_BOTH  ; break;
2544         case SvxBreak::PageBefore:     eBreak = style::BreakType_PAGE_BEFORE  ; break;
2545         case SvxBreak::PageAfter:      eBreak = style::BreakType_PAGE_AFTER   ; break;
2546         case SvxBreak::PageBoth:       eBreak = style::BreakType_PAGE_BOTH    ; break;
2547         default: ; // prevent warning
2548     }
2549     rVal <<= eBreak;
2550     return true;
2551 }
2552 
2553 bool SvxFormatBreakItem::PutValue( const uno::Any& rVal, sal_uInt8 /*nMemberId*/ )
2554 {
2555     style::BreakType nBreak;
2556 
2557     if(!(rVal >>= nBreak))
2558     {
2559         sal_Int32 nValue = 0;
2560         if(!(rVal >>= nValue))
2561             return false;
2562 
2563         nBreak = static_cast<style::BreakType>(nValue);
2564     }
2565 
2566     SvxBreak eBreak = SvxBreak::NONE;
2567     switch( nBreak )
2568     {
2569         case style::BreakType_COLUMN_BEFORE:    eBreak = SvxBreak::ColumnBefore; break;
2570         case style::BreakType_COLUMN_AFTER: eBreak = SvxBreak::ColumnAfter;  break;
2571         case style::BreakType_COLUMN_BOTH:      eBreak = SvxBreak::ColumnBoth;   break;
2572         case style::BreakType_PAGE_BEFORE:      eBreak = SvxBreak::PageBefore;   break;
2573         case style::BreakType_PAGE_AFTER:       eBreak = SvxBreak::PageAfter;    break;
2574         case style::BreakType_PAGE_BOTH:        eBreak = SvxBreak::PageBoth;     break;
2575         default: ; // prevent warning
2576     }
2577     SetValue(eBreak);
2578 
2579     return true;
2580 }
2581 
2582 SvxFormatBreakItem* SvxFormatBreakItem::Clone( SfxItemPool* ) const
2583 {
2584     return new SvxFormatBreakItem( *this );
2585 }
2586 
2587 sal_uInt16 SvxFormatBreakItem::GetValueCount() const
2588 {
2589     return sal_uInt16(SvxBreak::End);   // SvxBreak::PageBoth + 1
2590 }
2591 
2592 SvxFormatKeepItem* SvxFormatKeepItem::Clone( SfxItemPool* ) const
2593 {
2594     return new SvxFormatKeepItem( *this );
2595 }
2596 
2597 bool SvxFormatKeepItem::GetPresentation
2598 (
2599     SfxItemPresentation /*ePres*/,
2600     MapUnit             /*eCoreUnit*/,
2601     MapUnit             /*ePresUnit*/,
2602     OUString&           rText, const IntlWrapper&
2603     ) const
2604 {
2605     const char* pId = RID_SVXITEMS_FMTKEEP_FALSE;
2606 
2607     if ( GetValue() )
2608         pId = RID_SVXITEMS_FMTKEEP_TRUE;
2609     rText = EditResId(pId);
2610     return true;
2611 }
2612 
2613 
2614 SvxLineItem::SvxLineItem( const sal_uInt16 nId ) :
2615     SfxPoolItem ( nId )
2616 {
2617 }
2618 
2619 
2620 SvxLineItem::SvxLineItem( const SvxLineItem& rCpy ) :
2621     SfxPoolItem ( rCpy ),
2622     pLine(rCpy.pLine ? new SvxBorderLine( *rCpy.pLine ) : nullptr)
2623 {
2624 }
2625 
2626 
2627 SvxLineItem::~SvxLineItem()
2628 {
2629 }
2630 
2631 
2632 bool SvxLineItem::operator==( const SfxPoolItem& rAttr ) const
2633 {
2634     assert(SfxPoolItem::operator==(rAttr));
2635 
2636     return CmpBrdLn( pLine, static_cast<const SvxLineItem&>(rAttr).GetLine() );
2637 }
2638 
2639 SvxLineItem* SvxLineItem::Clone( SfxItemPool* ) const
2640 {
2641     return new SvxLineItem( *this );
2642 }
2643 
2644 bool SvxLineItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemId ) const
2645 {
2646     bool bConvert = 0!=(nMemId&CONVERT_TWIPS);
2647     nMemId &= ~CONVERT_TWIPS;
2648     if ( nMemId == 0 )
2649     {
2650         rVal <<= SvxBoxItem::SvxLineToLine(pLine.get(), bConvert);
2651         return true;
2652     }
2653     else if ( pLine )
2654     {
2655         switch ( nMemId )
2656         {
2657             case MID_FG_COLOR:      rVal <<= pLine->GetColor(); break;
2658             case MID_OUTER_WIDTH:   rVal <<= sal_Int32(pLine->GetOutWidth());   break;
2659             case MID_INNER_WIDTH:   rVal <<= sal_Int32(pLine->GetInWidth( ));   break;
2660             case MID_DISTANCE:      rVal <<= sal_Int32(pLine->GetDistance());   break;
2661             default:
2662                 OSL_FAIL( "Wrong MemberId" );
2663                 return false;
2664         }
2665     }
2666 
2667     return true;
2668 }
2669 
2670 
2671 bool SvxLineItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemId )
2672 {
2673     bool bConvert = 0!=(nMemId&CONVERT_TWIPS);
2674     nMemId &= ~CONVERT_TWIPS;
2675     sal_Int32 nVal = 0;
2676     if ( nMemId == 0 )
2677     {
2678         table::BorderLine2 aLine;
2679         if ( lcl_extractBorderLine(rVal, aLine) )
2680         {
2681             if ( !pLine )
2682                 pLine.reset( new SvxBorderLine );
2683             if( !SvxBoxItem::LineToSvxLine(aLine, *pLine, bConvert) )
2684                 pLine.reset();
2685             return true;
2686         }
2687         return false;
2688     }
2689     else if ( rVal >>= nVal )
2690     {
2691         if ( !pLine )
2692             pLine.reset( new SvxBorderLine );
2693 
2694         switch ( nMemId )
2695         {
2696             case MID_FG_COLOR:      pLine->SetColor( Color(nVal) ); break;
2697             case MID_LINE_STYLE:
2698                 pLine->SetBorderLineStyle(static_cast<SvxBorderLineStyle>(nVal));
2699             break;
2700             default:
2701                 OSL_FAIL( "Wrong MemberId" );
2702                 return false;
2703         }
2704 
2705         return true;
2706     }
2707 
2708     return false;
2709 }
2710 
2711 
2712 bool SvxLineItem::GetPresentation
2713 (
2714     SfxItemPresentation ePres,
2715     MapUnit             eCoreUnit,
2716     MapUnit             ePresUnit,
2717     OUString&           rText, const IntlWrapper& rIntl
2718 )   const
2719 {
2720     rText.clear();
2721 
2722     if ( pLine )
2723         rText = pLine->GetValueString( eCoreUnit, ePresUnit, &rIntl,
2724             (SfxItemPresentation::Complete == ePres) );
2725     return true;
2726 }
2727 
2728 
2729 void SvxLineItem::ScaleMetrics( long nMult, long nDiv )
2730 {
2731     if ( pLine ) pLine->ScaleMetrics( nMult, nDiv );
2732 }
2733 
2734 
2735 bool SvxLineItem::HasMetrics() const
2736 {
2737     return true;
2738 }
2739 
2740 
2741 void SvxLineItem::SetLine( const SvxBorderLine* pNew )
2742 {
2743     pLine.reset( pNew ? new SvxBorderLine( *pNew ) : nullptr );
2744 }
2745 
2746 SvxBrushItem::SvxBrushItem(sal_uInt16 _nWhich)
2747     : SfxPoolItem(_nWhich)
2748     , aColor(COL_TRANSPARENT)
2749     , nShadingValue(ShadingPattern::CLEAR)
2750     , nGraphicTransparency(0)
2751     , eGraphicPos(GPOS_NONE)
2752     , bLoadAgain(true)
2753 {
2754 }
2755 
2756 SvxBrushItem::SvxBrushItem(const Color& rColor, sal_uInt16 _nWhich)
2757     : SfxPoolItem(_nWhich)
2758     , aColor(rColor)
2759     , nShadingValue(ShadingPattern::CLEAR)
2760     , nGraphicTransparency(0)
2761     , eGraphicPos(GPOS_NONE)
2762     , bLoadAgain(true)
2763 {
2764 }
2765 
2766 SvxBrushItem::SvxBrushItem(const Graphic& rGraphic, SvxGraphicPosition ePos, sal_uInt16 _nWhich)
2767     : SfxPoolItem(_nWhich)
2768     , aColor(COL_TRANSPARENT)
2769     , nShadingValue(ShadingPattern::CLEAR)
2770     , xGraphicObject(new GraphicObject(rGraphic))
2771     , nGraphicTransparency(0)
2772     , eGraphicPos((GPOS_NONE != ePos) ? ePos : GPOS_MM)
2773     , bLoadAgain(true)
2774 {
2775     DBG_ASSERT( GPOS_NONE != ePos, "SvxBrushItem-Ctor with GPOS_NONE == ePos" );
2776 }
2777 
2778 SvxBrushItem::SvxBrushItem(const GraphicObject& rGraphicObj, SvxGraphicPosition ePos, sal_uInt16 _nWhich)
2779     : SfxPoolItem(_nWhich)
2780     , aColor(COL_TRANSPARENT)
2781     , nShadingValue(ShadingPattern::CLEAR)
2782     , xGraphicObject(new GraphicObject(rGraphicObj))
2783     , nGraphicTransparency(0)
2784     , eGraphicPos((GPOS_NONE != ePos) ? ePos : GPOS_MM)
2785     , bLoadAgain(true)
2786 {
2787     DBG_ASSERT( GPOS_NONE != ePos, "SvxBrushItem-Ctor with GPOS_NONE == ePos" );
2788 }
2789 
2790 SvxBrushItem::SvxBrushItem(const OUString& rLink, const OUString& rFilter,
2791                            SvxGraphicPosition ePos, sal_uInt16 _nWhich)
2792     : SfxPoolItem(_nWhich)
2793     , aColor(COL_TRANSPARENT)
2794     , nShadingValue(ShadingPattern::CLEAR)
2795     , nGraphicTransparency(0)
2796     , maStrLink(rLink)
2797     , maStrFilter(rFilter)
2798     , eGraphicPos((GPOS_NONE != ePos) ? ePos : GPOS_MM)
2799     , bLoadAgain(true)
2800 {
2801     DBG_ASSERT( GPOS_NONE != ePos, "SvxBrushItem-Ctor with GPOS_NONE == ePos" );
2802 }
2803 
2804 SvxBrushItem::SvxBrushItem(const SvxBrushItem& rItem)
2805     : SfxPoolItem(rItem)
2806     , aColor(rItem.aColor)
2807     , nShadingValue(rItem.nShadingValue)
2808     , xGraphicObject(rItem.xGraphicObject ? new GraphicObject(*rItem.xGraphicObject) : nullptr)
2809     , nGraphicTransparency(rItem.nGraphicTransparency)
2810     , maStrLink(rItem.maStrLink)
2811     , maStrFilter(rItem.maStrFilter)
2812     , eGraphicPos(rItem.eGraphicPos)
2813     , bLoadAgain(rItem.bLoadAgain)
2814 {
2815 }
2816 
2817 SvxBrushItem::SvxBrushItem(SvxBrushItem&& rItem)
2818     : SfxPoolItem(std::move(rItem))
2819     , aColor(std::move(rItem.aColor))
2820     , nShadingValue(std::move(rItem.nShadingValue))
2821     , xGraphicObject(std::move(rItem.xGraphicObject))
2822     , nGraphicTransparency(std::move(rItem.nGraphicTransparency))
2823     , maStrLink(std::move(rItem.maStrLink))
2824     , maStrFilter(std::move(rItem.maStrFilter))
2825     , eGraphicPos(std::move(rItem.eGraphicPos))
2826     , bLoadAgain(std::move(rItem.bLoadAgain))
2827 {
2828 }
2829 
2830 SvxBrushItem::~SvxBrushItem()
2831 {
2832 }
2833 
2834 bool SvxBrushItem::isUsed() const
2835 {
2836     if (GPOS_NONE != GetGraphicPos())
2837     {
2838         // graphic used
2839         return true;
2840     }
2841     else if (0xff != GetColor().GetTransparency())
2842     {
2843         // color used
2844         return true;
2845     }
2846 
2847     return false;
2848 }
2849 
2850 
2851 static sal_Int8 lcl_PercentToTransparency(long nPercent)
2852 {
2853     // 0xff must not be returned!
2854     return sal_Int8(nPercent ? (50 + 0xfe * nPercent) / 100 : 0);
2855 }
2856 
2857 
2858 sal_Int8 SvxBrushItem::TransparencyToPercent(sal_Int32 nTrans)
2859 {
2860     return static_cast<sal_Int8>((nTrans * 100 + 127) / 254);
2861 }
2862 
2863 
2864 bool SvxBrushItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
2865 {
2866     nMemberId &= ~CONVERT_TWIPS;
2867     switch( nMemberId)
2868     {
2869         case MID_BACK_COLOR:
2870             rVal <<= aColor;
2871         break;
2872         case MID_BACK_COLOR_R_G_B:
2873             rVal <<= aColor.GetRGBColor();
2874         break;
2875         case MID_BACK_COLOR_TRANSPARENCY:
2876             rVal <<= SvxBrushItem::TransparencyToPercent(aColor.GetTransparency());
2877         break;
2878         case MID_GRAPHIC_POSITION:
2879             rVal <<= static_cast<style::GraphicLocation>(static_cast<sal_Int16>(eGraphicPos));
2880         break;
2881 
2882         case MID_GRAPHIC_TRANSPARENT:
2883             rVal <<= ( aColor.GetTransparency() == 0xff );
2884         break;
2885 
2886         case MID_GRAPHIC_URL:
2887         {
2888             SAL_INFO("editeng.items", "Getting GraphicURL property is not supported");
2889             return false;
2890         }
2891         break;
2892         case MID_GRAPHIC:
2893         {
2894             uno::Reference<graphic::XGraphic> xGraphic;
2895             if (!maStrLink.isEmpty())
2896             {
2897                 Graphic aGraphic(vcl::graphic::loadFromURL(maStrLink));
2898                 xGraphic = aGraphic.GetXGraphic();
2899             }
2900             else if (xGraphicObject)
2901             {
2902                 xGraphic = xGraphicObject->GetGraphic().GetXGraphic();
2903             }
2904             rVal <<= xGraphic;
2905         }
2906         break;
2907 
2908         case MID_GRAPHIC_FILTER:
2909         {
2910             rVal <<= maStrFilter;
2911         }
2912         break;
2913 
2914         case MID_GRAPHIC_TRANSPARENCY:
2915             rVal <<= nGraphicTransparency;
2916         break;
2917 
2918         case MID_SHADING_VALUE:
2919         {
2920             rVal <<= nShadingValue;
2921         }
2922         break;
2923     }
2924 
2925     return true;
2926 }
2927 
2928 
2929 bool SvxBrushItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
2930 {
2931     nMemberId &= ~CONVERT_TWIPS;
2932     switch( nMemberId)
2933     {
2934         case MID_BACK_COLOR:
2935         case MID_BACK_COLOR_R_G_B:
2936         {
2937             Color aNewCol;
2938             if ( !( rVal >>= aNewCol ) )
2939                 return false;
2940             if(MID_BACK_COLOR_R_G_B == nMemberId)
2941             {
2942                 aNewCol.SetTransparency(aColor.GetTransparency());
2943             }
2944             aColor = aNewCol;
2945         }
2946         break;
2947         case MID_BACK_COLOR_TRANSPARENCY:
2948         {
2949             sal_Int32 nTrans = 0;
2950             if ( !( rVal >>= nTrans ) || nTrans < 0 || nTrans > 100 )
2951                 return false;
2952             aColor.SetTransparency(lcl_PercentToTransparency(nTrans));
2953         }
2954         break;
2955 
2956         case MID_GRAPHIC_POSITION:
2957         {
2958             style::GraphicLocation eLocation;
2959             if ( !( rVal>>=eLocation ) )
2960             {
2961                 sal_Int32 nValue = 0;
2962                 if ( !( rVal >>= nValue ) )
2963                     return false;
2964                 eLocation = static_cast<style::GraphicLocation>(nValue);
2965             }
2966             SetGraphicPos( static_cast<SvxGraphicPosition>(static_cast<sal_uInt16>(eLocation)) );
2967         }
2968         break;
2969 
2970         case MID_GRAPHIC_TRANSPARENT:
2971             aColor.SetTransparency( Any2Bool( rVal ) ? 0xff : 0 );
2972         break;
2973 
2974         case MID_GRAPHIC_URL:
2975         case MID_GRAPHIC:
2976         {
2977             Graphic aGraphic;
2978 
2979             if (rVal.getValueType() == ::cppu::UnoType<OUString>::get())
2980             {
2981                 OUString aURL = rVal.get<OUString>();
2982                 aGraphic = vcl::graphic::loadFromURL(aURL);
2983             }
2984             else if (rVal.getValueType() == cppu::UnoType<graphic::XGraphic>::get())
2985             {
2986                 auto xGraphic = rVal.get<uno::Reference<graphic::XGraphic>>();
2987                 aGraphic = Graphic(xGraphic);
2988             }
2989 
2990             if (!aGraphic.IsNone())
2991             {
2992                 maStrLink.clear();
2993 
2994                 std::unique_ptr<GraphicObject> xOldGrfObj(std::move(xGraphicObject));
2995                 xGraphicObject.reset(new GraphicObject(aGraphic));
2996                 ApplyGraphicTransparency_Impl();
2997                 xOldGrfObj.reset();
2998 
2999                 if (!aGraphic.IsNone() && eGraphicPos == GPOS_NONE)
3000                 {
3001                     eGraphicPos = GPOS_MM;
3002                 }
3003                 else if (aGraphic.IsNone())
3004                 {
3005                     eGraphicPos = GPOS_NONE;
3006                 }
3007             }
3008         }
3009         break;
3010 
3011         case MID_GRAPHIC_FILTER:
3012         {
3013             if( rVal.getValueType() == ::cppu::UnoType<OUString>::get() )
3014             {
3015                 OUString sLink;
3016                 rVal >>= sLink;
3017                 SetGraphicFilter( sLink );
3018             }
3019         }
3020         break;
3021         case MID_GRAPHIC_TRANSPARENCY :
3022         {
3023             sal_Int32 nTmp = 0;
3024             rVal >>= nTmp;
3025             if(nTmp >= 0 && nTmp <= 100)
3026             {
3027                 nGraphicTransparency = sal_Int8(nTmp);
3028                 if (xGraphicObject)
3029                     ApplyGraphicTransparency_Impl();
3030             }
3031         }
3032         break;
3033 
3034         case MID_SHADING_VALUE:
3035         {
3036             sal_Int32 nVal = 0;
3037             if (!(rVal >>= nVal))
3038                 return false;
3039 
3040             nShadingValue = nVal;
3041         }
3042         break;
3043     }
3044 
3045     return true;
3046 }
3047 
3048 
3049 bool SvxBrushItem::GetPresentation
3050 (
3051     SfxItemPresentation /*ePres*/,
3052     MapUnit             /*eCoreUnit*/,
3053     MapUnit             /*ePresUnit*/,
3054     OUString&           rText, const IntlWrapper&
3055     ) const
3056 {
3057     if ( GPOS_NONE  == eGraphicPos )
3058     {
3059         rText = ::GetColorString( aColor ) + cpDelim;
3060         const char* pId = RID_SVXITEMS_TRANSPARENT_FALSE;
3061 
3062         if ( aColor.GetTransparency() )
3063             pId = RID_SVXITEMS_TRANSPARENT_TRUE;
3064         rText += EditResId(pId);
3065     }
3066     else
3067     {
3068         rText = EditResId(RID_SVXITEMS_GRAPHIC);
3069     }
3070 
3071     return true;
3072 }
3073 
3074 bool SvxBrushItem::operator==( const SfxPoolItem& rAttr ) const
3075 {
3076     assert(SfxPoolItem::operator==(rAttr));
3077 
3078     const SvxBrushItem& rCmp = static_cast<const SvxBrushItem&>(rAttr);
3079     bool bEqual = ( aColor == rCmp.aColor && eGraphicPos == rCmp.eGraphicPos &&
3080         nGraphicTransparency == rCmp.nGraphicTransparency);
3081 
3082     if ( bEqual )
3083     {
3084         if ( GPOS_NONE != eGraphicPos )
3085         {
3086             bEqual = maStrLink == rCmp.maStrLink;
3087 
3088             if ( bEqual )
3089             {
3090                 bEqual = maStrFilter == rCmp.maStrFilter;
3091             }
3092 
3093             if ( bEqual )
3094             {
3095                 if (!rCmp.xGraphicObject)
3096                     bEqual = !xGraphicObject;
3097                 else
3098                     bEqual = xGraphicObject &&
3099                              (*xGraphicObject == *rCmp.xGraphicObject);
3100             }
3101         }
3102 
3103         if (bEqual)
3104         {
3105             bEqual = nShadingValue == rCmp.nShadingValue;
3106         }
3107     }
3108 
3109     return bEqual;
3110 }
3111 
3112 SvxBrushItem* SvxBrushItem::Clone( SfxItemPool* ) const
3113 {
3114     return new SvxBrushItem( *this );
3115 }
3116 
3117 const GraphicObject* SvxBrushItem::GetGraphicObject(OUString const & referer) const
3118 {
3119     if (bLoadAgain && !maStrLink.isEmpty() && !xGraphicObject)
3120     // when graphics already loaded, use as a cache
3121     {
3122         if (maSecOptions.isUntrustedReferer(referer)) {
3123             return nullptr;
3124         }
3125 
3126         // tdf#94088 prepare graphic and state
3127         Graphic aGraphic;
3128         bool bGraphicLoaded = false;
3129 
3130         // try to create stream directly from given URL
3131         std::unique_ptr<SvStream> xStream(utl::UcbStreamHelper::CreateStream(maStrLink, StreamMode::STD_READ));
3132         // tdf#94088 if we have a stream, try to load it directly as graphic
3133         if (xStream && !xStream->GetError())
3134         {
3135             if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, maStrLink, *xStream,
3136                 GRFILTER_FORMAT_DONTKNOW, nullptr, GraphicFilterImportFlags::DontSetLogsizeForJpeg))
3137             {
3138                 bGraphicLoaded = true;
3139             }
3140         }
3141 
3142         // tdf#94088 if no succeeded, try if the string (which is not empty) contains
3143         // a 'data:' scheme url and try to load that (embedded graphics)
3144         if(!bGraphicLoaded)
3145         {
3146             INetURLObject aGraphicURL( maStrLink );
3147 
3148             if( INetProtocol::Data == aGraphicURL.GetProtocol() )
3149             {
3150                 std::unique_ptr<SvMemoryStream> const xMemStream(aGraphicURL.getData());
3151                 if (xMemStream)
3152                 {
3153                     if (ERRCODE_NONE == GraphicFilter::GetGraphicFilter().ImportGraphic(aGraphic, "", *xMemStream))
3154                     {
3155                         bGraphicLoaded = true;
3156 
3157                         // tdf#94088 delete the no longer needed data scheme URL which
3158                         // is potentially pretty // large, containing a base64 encoded copy of the graphic
3159                         const_cast< SvxBrushItem* >(this)->maStrLink.clear();
3160                     }
3161                 }
3162             }
3163         }
3164 
3165         // tdf#94088 when we got a graphic, set it
3166         if(bGraphicLoaded && GraphicType::NONE != aGraphic.GetType())
3167         {
3168             xGraphicObject.reset(new GraphicObject);
3169             xGraphicObject->SetGraphic(aGraphic);
3170             const_cast < SvxBrushItem*> (this)->ApplyGraphicTransparency_Impl();
3171         }
3172         else
3173         {
3174             bLoadAgain = false;
3175         }
3176     }
3177 
3178     return xGraphicObject.get();
3179 }
3180 
3181 void SvxBrushItem::setGraphicTransparency(sal_Int8 nNew)
3182 {
3183     if (nNew != nGraphicTransparency)
3184     {
3185         nGraphicTransparency = nNew;
3186         ApplyGraphicTransparency_Impl();
3187     }
3188 }
3189 
3190 const Graphic* SvxBrushItem::GetGraphic(OUString const & referer) const
3191 {
3192     const GraphicObject* pGrafObj = GetGraphicObject(referer);
3193     return( pGrafObj ? &( pGrafObj->GetGraphic() ) : nullptr );
3194 }
3195 
3196 void SvxBrushItem::SetGraphicPos( SvxGraphicPosition eNew )
3197 {
3198     eGraphicPos = eNew;
3199 
3200     if ( GPOS_NONE == eGraphicPos )
3201     {
3202         xGraphicObject.reset();
3203         maStrLink.clear();
3204         maStrFilter.clear();
3205     }
3206     else
3207     {
3208         if (!xGraphicObject && maStrLink.isEmpty())
3209         {
3210             xGraphicObject.reset(new GraphicObject); // Creating a dummy
3211         }
3212     }
3213 }
3214 
3215 void SvxBrushItem::SetGraphic( const Graphic& rNew )
3216 {
3217     if ( maStrLink.isEmpty() )
3218     {
3219         if (xGraphicObject)
3220             xGraphicObject->SetGraphic(rNew);
3221         else
3222             xGraphicObject.reset(new GraphicObject(rNew));
3223 
3224         ApplyGraphicTransparency_Impl();
3225 
3226         if ( GPOS_NONE == eGraphicPos )
3227             eGraphicPos = GPOS_MM; // None would be brush, then Default: middle
3228     }
3229     else
3230     {
3231         OSL_FAIL( "SetGraphic() on linked graphic! :-/" );
3232     }
3233 }
3234 
3235 void SvxBrushItem::SetGraphicObject( const GraphicObject& rNewObj )
3236 {
3237     if ( maStrLink.isEmpty() )
3238     {
3239         if (xGraphicObject)
3240             *xGraphicObject = rNewObj;
3241         else
3242             xGraphicObject.reset(new GraphicObject(rNewObj));
3243 
3244         ApplyGraphicTransparency_Impl();
3245 
3246         if ( GPOS_NONE == eGraphicPos )
3247             eGraphicPos = GPOS_MM; // None would be brush, then Default: middle
3248     }
3249     else
3250     {
3251         OSL_FAIL( "SetGraphic() on linked graphic! :-/" );
3252     }
3253 }
3254 
3255 void SvxBrushItem::SetGraphicLink( const OUString& rNew )
3256 {
3257     if ( rNew.isEmpty() )
3258         maStrLink.clear();
3259     else
3260     {
3261         maStrLink = rNew;
3262         xGraphicObject.reset();
3263     }
3264 }
3265 
3266 void SvxBrushItem::SetGraphicFilter( const OUString& rNew )
3267 {
3268     maStrFilter = rNew;
3269 }
3270 
3271 void SvxBrushItem::ApplyGraphicTransparency_Impl()
3272 {
3273     DBG_ASSERT(xGraphicObject, "no GraphicObject available" );
3274     if (xGraphicObject)
3275     {
3276         GraphicAttr aAttr(xGraphicObject->GetAttr());
3277         aAttr.SetTransparency(lcl_PercentToTransparency(
3278                             nGraphicTransparency));
3279         xGraphicObject->SetAttr(aAttr);
3280     }
3281 }
3282 
3283 void SvxBrushItem::dumpAsXml(xmlTextWriterPtr pWriter) const
3284 {
3285     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxBrushItem"));
3286     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), BAD_CAST(OString::number(Which()).getStr()));
3287     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("color"), BAD_CAST(aColor.AsRGBHexString().toUtf8().getStr()));
3288     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("shadingValue"), BAD_CAST(OString::number(nShadingValue).getStr()));
3289     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("link"), BAD_CAST(maStrLink.toUtf8().getStr()));
3290     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("filter"), BAD_CAST(maStrFilter.toUtf8().getStr()));
3291     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("graphicPos"), BAD_CAST(OString::number(eGraphicPos).getStr()));
3292     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("loadAgain"), BAD_CAST(OString::boolean(bLoadAgain).getStr()));
3293     xmlTextWriterEndElement(pWriter);
3294 }
3295 
3296 
3297 SvxFrameDirectionItem::SvxFrameDirectionItem( SvxFrameDirection nValue ,
3298                                             sal_uInt16 _nWhich )
3299     : SfxEnumItem<SvxFrameDirection>( _nWhich, nValue )
3300 {
3301 }
3302 
3303 
3304 SvxFrameDirectionItem::~SvxFrameDirectionItem()
3305 {
3306 }
3307 
3308 SvxFrameDirectionItem* SvxFrameDirectionItem::Clone( SfxItemPool * ) const
3309 {
3310     return new SvxFrameDirectionItem( *this );
3311 }
3312 
3313 const char* getFrmDirResId(size_t nIndex)
3314 {
3315     const char* const RID_SVXITEMS_FRMDIR[] =
3316     {
3317         RID_SVXITEMS_FRMDIR_HORI_LEFT_TOP,
3318         RID_SVXITEMS_FRMDIR_HORI_RIGHT_TOP,
3319         RID_SVXITEMS_FRMDIR_VERT_TOP_RIGHT,
3320         RID_SVXITEMS_FRMDIR_VERT_TOP_LEFT,
3321         RID_SVXITEMS_FRMDIR_ENVIRONMENT,
3322         RID_SVXITEMS_FRMDIR_VERT_BOT_LEFT
3323     };
3324     return RID_SVXITEMS_FRMDIR[nIndex];
3325 }
3326 
3327 bool SvxFrameDirectionItem::GetPresentation(
3328     SfxItemPresentation /*ePres*/,
3329     MapUnit             /*eCoreUnit*/,
3330     MapUnit             /*ePresUnit*/,
3331     OUString&           rText, const IntlWrapper&) const
3332 {
3333     rText = EditResId(getFrmDirResId(GetEnumValue()));
3334     return true;
3335 }
3336 
3337 bool SvxFrameDirectionItem::PutValue( const css::uno::Any& rVal,
3338                                              sal_uInt8 )
3339 {
3340     sal_Int16 nVal = sal_Int16();
3341     bool bRet = ( rVal >>= nVal );
3342     if( bRet )
3343     {
3344         // translate WritingDirection2 constants into SvxFrameDirection
3345         switch( nVal )
3346         {
3347             case text::WritingMode2::LR_TB:
3348                 SetValue( SvxFrameDirection::Horizontal_LR_TB );
3349                 break;
3350             case text::WritingMode2::RL_TB:
3351                 SetValue( SvxFrameDirection::Horizontal_RL_TB );
3352                 break;
3353             case text::WritingMode2::TB_RL:
3354                 SetValue( SvxFrameDirection::Vertical_RL_TB );
3355                 break;
3356             case text::WritingMode2::TB_LR:
3357                 SetValue( SvxFrameDirection::Vertical_LR_TB );
3358                 break;
3359             case text::WritingMode2::BT_LR:
3360                 SetValue( SvxFrameDirection::Vertical_LR_BT );
3361                 break;
3362             case text::WritingMode2::PAGE:
3363                 SetValue( SvxFrameDirection::Environment );
3364                 break;
3365             default:
3366                 bRet = false;
3367                 break;
3368         }
3369     }
3370 
3371     return bRet;
3372 }
3373 
3374 
3375 bool SvxFrameDirectionItem::QueryValue( css::uno::Any& rVal,
3376                                             sal_uInt8 ) const
3377 {
3378     // translate SvxFrameDirection into WritingDirection2
3379     sal_Int16 nVal;
3380     bool bRet = true;
3381     switch( GetValue() )
3382     {
3383         case SvxFrameDirection::Horizontal_LR_TB:
3384             nVal = text::WritingMode2::LR_TB;
3385             break;
3386         case SvxFrameDirection::Horizontal_RL_TB:
3387             nVal = text::WritingMode2::RL_TB;
3388             break;
3389         case SvxFrameDirection::Vertical_RL_TB:
3390             nVal = text::WritingMode2::TB_RL;
3391             break;
3392         case SvxFrameDirection::Vertical_LR_TB:
3393             nVal = text::WritingMode2::TB_LR;
3394             break;
3395         case SvxFrameDirection::Vertical_LR_BT:
3396             nVal = text::WritingMode2::BT_LR;
3397             break;
3398         case SvxFrameDirection::Environment:
3399             nVal = text::WritingMode2::PAGE;
3400             break;
3401         default:
3402             OSL_FAIL("Unknown SvxFrameDirection value!");
3403             bRet = false;
3404             break;
3405     }
3406 
3407     // return value + error state
3408     if( bRet )
3409     {
3410         rVal <<= nVal;
3411     }
3412     return bRet;
3413 }
3414 
3415 void SvxFrameDirectionItem::dumpAsXml(xmlTextWriterPtr pWriter) const
3416 {
3417     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxFrameDirectionItem"));
3418     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("m_nWhich"),
3419                                 BAD_CAST(OString::number(Which()).getStr()));
3420     xmlTextWriterWriteAttribute(
3421         pWriter, BAD_CAST("m_nValue"),
3422         BAD_CAST(OString::number(static_cast<sal_Int16>(GetValue())).getStr()));
3423     xmlTextWriterEndElement(pWriter);
3424 }
3425 
3426 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
3427