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