sc: factor out some more code
[LibreOffice.git] / sw / source / filter / xml / xmlimpit.cxx
blob59678acf33efcc9e1496bf64bd321048716a2b56
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xmlimpit.hxx"
22 #include <sal/log.hxx>
23 #include <sax/tools/converter.hxx>
24 #include <utility>
25 #include <xmloff/xmluconv.hxx>
26 #include <svl/itempool.hxx>
27 #include <svl/poolitem.hxx>
28 #include <svl/itemset.hxx>
29 #include <xmloff/namespacemap.hxx>
30 #include <editeng/xmlcnitm.hxx>
31 #include <editeng/memberids.h>
32 #include <osl/diagnose.h>
34 #include <hintids.hxx>
35 #include <unomid.h>
36 #include <svx/unomid.hxx>
37 #include <editeng/lrspitem.hxx>
38 #include <editeng/ulspitem.hxx>
39 #include <editeng/shaditem.hxx>
40 #include <editeng/boxitem.hxx>
41 #include <editeng/formatbreakitem.hxx>
42 #include <editeng/keepitem.hxx>
43 #include <editeng/brushitem.hxx>
44 #include <editeng/frmdir.hxx>
45 #include <fmtpdsc.hxx>
46 #include <fmtornt.hxx>
47 #include <fmtfsize.hxx>
49 #include <xmloff/prhdlfac.hxx>
50 #include <xmloff/xmltypes.hxx>
51 #include <xmloff/xmlprhdl.hxx>
52 #include <xmloff/xmlimp.hxx>
53 #include <xmloff/xmlnamespace.hxx>
54 #include "xmlithlp.hxx"
55 #include <com/sun/star/uno/Any.hxx>
57 using ::editeng::SvxBorderLine;
58 using namespace ::com::sun::star;
59 using namespace ::xmloff::token;
60 using uno::Any;
62 constexpr sal_uInt16 nUnknownWhich = RES_UNKNOWNATR_CONTAINER;
64 SvXMLImportItemMapper::SvXMLImportItemMapper(
65 SvXMLItemMapEntriesRef aMapEntries ) :
66 mrMapEntries(std::move( aMapEntries ))
70 SvXMLImportItemMapper::~SvXMLImportItemMapper()
74 void
75 SvXMLImportItemMapper::setMapEntries(const SvXMLItemMapEntriesRef& rMapEntries)
77 mrMapEntries = rMapEntries;
80 // fills the given itemset with the attributes in the given list
81 void SvXMLImportItemMapper::importXML( SfxItemSet& rSet,
82 uno::Reference< xml::sax::XFastAttributeList > const & xAttrList,
83 const SvXMLUnitConverter& rUnitConverter,
84 const SvXMLNamespaceMap& rNamespaceMap )
86 std::unique_ptr<SvXMLAttrContainerItem> pUnknownItem;
87 for (auto &aIter : sax_fastparser::castToFastAttributeList( xAttrList ))
89 if( IsTokenInNamespace(aIter.getToken(), XML_NAMESPACE_XMLNS) )
90 continue;
92 sal_Int32 nToken = aIter.getToken();
93 const OUString sValue = aIter.toString();
95 // find a map entry for this attribute
96 sal_Int32 nLookupToken = nToken;
97 // compatibility namespaces need to be transformed into current namespace before looking up
98 if (IsTokenInNamespace(nLookupToken, XML_NAMESPACE_FO_COMPAT))
99 nLookupToken = XML_ELEMENT(FO, (nLookupToken & TOKEN_MASK));
100 SvXMLItemMapEntry const * pEntry = mrMapEntries->getByName( nLookupToken );
102 if( pEntry )
104 // we have a valid map entry here, so let's use it...
105 if( 0 == (pEntry->nMemberId & (MID_SW_FLAG_NO_ITEM_IMPORT|
106 MID_SW_FLAG_ELEMENT_ITEM_IMPORT)) )
108 // first get item from itemset
109 const SfxPoolItem* pItem = nullptr;
110 SfxItemState eState = rSet.GetItemState( pEntry->nWhichId, true,
111 &pItem );
113 // if it's not set, try the pool
114 if (SfxItemState::SET != eState && SfxItemPool::IsWhich(pEntry->nWhichId))
115 pItem = &rSet.GetPool()->GetUserOrPoolDefaultItem(pEntry->nWhichId);
117 // do we have an item?
118 if(eState >= SfxItemState::DEFAULT && pItem)
120 std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone());
121 bool bPut = false;
123 if( 0 == (pEntry->nMemberId&MID_SW_FLAG_SPECIAL_ITEM_IMPORT) )
125 bPut = PutXMLValue( *pNewItem, sValue,
126 o3tl::narrowing<sal_uInt16>( pEntry->nMemberId & MID_SW_FLAG_MASK ),
127 rUnitConverter );
130 else
132 bPut = handleSpecialItem( *pEntry, *pNewItem, rSet,
133 sValue, rUnitConverter );
136 if( bPut )
137 rSet.Put( std::move(pNewItem) );
139 else
141 OSL_FAIL( "Could not get a needed item for xml import!" );
144 else if( 0 != (pEntry->nMemberId & MID_SW_FLAG_NO_ITEM_IMPORT) )
146 handleNoItem( *pEntry, rSet, sValue, rUnitConverter,
147 rNamespaceMap );
150 else
152 if( !pUnknownItem )
154 const SfxPoolItem* pItem = nullptr;
155 if( SfxItemState::SET == rSet.GetItemState( nUnknownWhich, true,
156 &pItem ) )
158 pUnknownItem.reset( static_cast<SvXMLAttrContainerItem*>( pItem->Clone() ) );
160 else
162 pUnknownItem.reset( new SvXMLAttrContainerItem( nUnknownWhich ) );
165 if( pUnknownItem )
167 if( IsTokenInNamespace(nToken, XML_NAMESPACE_NONE) )
168 pUnknownItem->AddAttr( SvXMLImport::getNameFromToken( nToken ), sValue );
169 else
171 const OUString aAttrNamespacePrefix = SvXMLImport::getNamespacePrefixFromToken(nToken, &rNamespaceMap);
172 OUString sAttrName = SvXMLImport::getNameFromToken( nToken );
173 if ( !aAttrNamespacePrefix.isEmpty() )
174 sAttrName = aAttrNamespacePrefix + SvXMLImport::aNamespaceSeparator + sAttrName;
175 OUString aLocalName, aPrefix, aNamespace;
176 rNamespaceMap.GetKeyByAttrName( sAttrName, &aPrefix, &aLocalName,
177 &aNamespace );
178 if ( !aAttrNamespacePrefix.isEmpty() )
179 pUnknownItem->AddAttr( aAttrNamespacePrefix, aNamespace, aLocalName,
180 sValue );
181 else
182 pUnknownItem->AddAttr( aLocalName, sValue );
188 importXMLUnknownAttributes(rSet, xAttrList, rUnitConverter, pUnknownItem);
190 if( pUnknownItem )
192 rSet.Put( *pUnknownItem );
195 finished(rSet, rUnitConverter);
198 void SvXMLImportItemMapper::importXMLUnknownAttributes( SfxItemSet& rSet,
199 uno::Reference< xml::sax::XFastAttributeList > const & xAttrList,
200 const SvXMLUnitConverter& rUnitConverter,
201 std::unique_ptr<SvXMLAttrContainerItem>& pUnknownItem)
203 const css::uno::Sequence< css::xml::Attribute > unknownAttributes = xAttrList->getUnknownAttributes();
204 for (const auto & rAttribute : unknownAttributes)
206 if( !pUnknownItem )
208 const SfxPoolItem* pItem = nullptr;
209 if( SfxItemState::SET == rSet.GetItemState( nUnknownWhich, true,
210 &pItem ) )
212 pUnknownItem.reset( static_cast<SvXMLAttrContainerItem*>( pItem->Clone() ) );
214 else
216 pUnknownItem.reset( new SvXMLAttrContainerItem( nUnknownWhich ) );
219 if( pUnknownItem )
221 if( rAttribute.NamespaceURL.isEmpty() )
222 pUnknownItem->AddAttr( rAttribute.Name, rAttribute.Value );
223 else
225 OUString sPrefix;
226 OUString sName = rAttribute.Name;
227 int i = sName.indexOf(':');
228 if (i != -1)
230 sPrefix = sName.copy(0, i);
231 sName = sName.copy(i+1);
233 // the sax parser doesn't reject these, strangely
234 if (sName.indexOf(':') == -1)
235 pUnknownItem->AddAttr( sPrefix, rAttribute.NamespaceURL, sName,
236 rAttribute.Value );
237 else
238 SAL_WARN("sw", "ignoring dodgy attribute: " + rAttribute.Name);
243 if( pUnknownItem )
245 rSet.Put( *pUnknownItem );
248 finished(rSet, rUnitConverter);
251 /** this method is called for every item that has the
252 MID_SW_FLAG_SPECIAL_ITEM_IMPORT flag set */
253 bool
254 SvXMLImportItemMapper::handleSpecialItem( const SvXMLItemMapEntry& /*rEntry*/,
255 SfxPoolItem& /*rItem*/,
256 SfxItemSet& /*rSet*/,
257 const OUString& /*rValue*/,
258 const SvXMLUnitConverter& /*rUnitConverter*/ )
260 OSL_FAIL( "unsupported special item in xml import" );
261 return false;
264 /** this method is called for every item that has the
265 MID_SW_FLAG_NO_ITEM_IMPORT flag set */
266 bool SvXMLImportItemMapper::handleNoItem( const SvXMLItemMapEntry& /*rEntry*/,
267 SfxItemSet& /*rSet*/,
268 const OUString& /*rValue*/,
269 const SvXMLUnitConverter& /*rUnitConverter*/,
270 const SvXMLNamespaceMap& /*rNamespaceMap*/ )
272 OSL_FAIL( "unsupported no item in xml import" );
273 return false;
276 void
277 SvXMLImportItemMapper::finished(SfxItemSet &, SvXMLUnitConverter const&) const
279 // nothing to do here
282 namespace {
284 struct BoxHolder
286 std::unique_ptr<SvxBorderLine> pTop;
287 std::unique_ptr<SvxBorderLine> pBottom;
288 std::unique_ptr<SvxBorderLine> pLeft;
289 std::unique_ptr<SvxBorderLine> pRight;
291 BoxHolder(BoxHolder const&) = delete;
292 BoxHolder& operator=(BoxHolder const&) = delete;
294 explicit BoxHolder(SvxBoxItem const & rBox)
296 if (rBox.GetTop())
297 pTop.reset(new SvxBorderLine( *rBox.GetTop() ));
298 if (rBox.GetBottom())
299 pBottom.reset(new SvxBorderLine( *rBox.GetBottom() ));
300 if (rBox.GetLeft())
301 pLeft.reset(new SvxBorderLine( *rBox.GetLeft() ));
302 if (rBox.GetRight())
303 pRight.reset(new SvxBorderLine( *rBox.GetRight() ));
309 // put an XML-string value into an item
310 bool SvXMLImportItemMapper::PutXMLValue(
311 SfxPoolItem& rItem,
312 const OUString& rValue,
313 sal_uInt16 nMemberId,
314 const SvXMLUnitConverter& rUnitConverter )
316 bool bOk = false;
318 switch (rItem.Which())
320 case RES_MARGIN_FIRSTLINE:
321 case RES_MARGIN_TEXTLEFT:
322 case RES_MARGIN_RIGHT:
323 assert(false); // is only called for frame formats?
324 break;
326 case RES_LR_SPACE:
328 SvxLRSpaceItem& rLRSpace = dynamic_cast<SvxLRSpaceItem&>(rItem);
330 switch( nMemberId )
332 case MID_L_MARGIN:
333 case MID_R_MARGIN:
335 sal_Int32 nProp = 100;
336 sal_Int32 nAbs = 0;
338 if( rValue.indexOf( '%' ) != -1 )
339 bOk = ::sax::Converter::convertPercent(nProp, rValue);
340 else
341 bOk = rUnitConverter.convertMeasureToCore(nAbs, rValue);
343 if( bOk )
345 switch( nMemberId )
347 case MID_L_MARGIN:
348 rLRSpace.SetTextLeft(SvxIndentValue::twips(nAbs),
349 o3tl::narrowing<sal_uInt16>(nProp));
350 break;
351 case MID_R_MARGIN:
352 rLRSpace.SetRight(SvxIndentValue::twips(nAbs),
353 o3tl::narrowing<sal_uInt16>(nProp));
354 break;
358 break;
360 case MID_FIRST_LINE_INDENT:
362 assert(false); // it looks like this can't be called? (frame formats only, aTableItemMap)
363 sal_Int32 nProp = 100;
364 sal_Int32 nAbs = 0;
366 if( rValue.indexOf( '%' ) != -1 )
367 bOk = ::sax::Converter::convertPercent(nProp, rValue);
368 else
369 bOk = rUnitConverter.convertMeasureToCore(nAbs, rValue,
370 -0x7fff, 0x7fff );
372 rLRSpace.SetTextFirstLineOffset(SvxIndentValue::twips(nAbs),
373 o3tl::narrowing<sal_uInt16>(nProp));
375 break;
377 case MID_FIRST_AUTO:
379 assert(false); // it looks like this can't be called? (frame formats only, aTableItemMap)
380 bool bAutoFirst(false);
381 bOk = ::sax::Converter::convertBool( bAutoFirst, rValue );
382 if( bOk )
383 rLRSpace.SetAutoFirst( bAutoFirst );
385 break;
387 default:
388 OSL_FAIL( "unknown member id!");
391 break;
393 case RES_UL_SPACE:
395 SvxULSpaceItem& rULSpace = dynamic_cast<SvxULSpaceItem&>(rItem);
397 sal_Int32 nProp = 100;
398 sal_Int32 nAbs = 0;
400 if( rValue.indexOf( '%' ) != -1 )
401 bOk = ::sax::Converter::convertPercent( nProp, rValue );
402 else
403 bOk = rUnitConverter.convertMeasureToCore( nAbs, rValue );
405 switch( nMemberId )
407 case MID_UP_MARGIN:
408 rULSpace.SetUpper( o3tl::narrowing<sal_uInt16>(nAbs), o3tl::narrowing<sal_uInt16>(nProp) );
409 break;
410 case MID_LO_MARGIN:
411 rULSpace.SetLower( o3tl::narrowing<sal_uInt16>(nAbs), o3tl::narrowing<sal_uInt16>(nProp) );
412 break;
413 default:
414 OSL_FAIL("unknown MemberId");
417 break;
419 case RES_SHADOW:
421 SvxShadowItem& rShadow = dynamic_cast<SvxShadowItem&>(rItem);
423 bool bColorFound = false;
424 bool bOffsetFound = false;
426 SvXMLTokenEnumerator aTokenEnum( rValue );
428 Color aColor( 128,128, 128 );
429 rShadow.SetLocation( SvxShadowLocation::BottomRight );
431 std::u16string_view aToken;
432 while( aTokenEnum.getNextToken( aToken ) )
434 if( IsXMLToken( aToken, XML_NONE ) )
436 rShadow.SetLocation( SvxShadowLocation::NONE );
437 bOk = true;
439 else if( !bColorFound && aToken.substr(0,1) == u"#" )
441 bOk = ::sax::Converter::convertColor( aColor, aToken );
442 if( !bOk )
443 return false;
445 bColorFound = true;
447 else if( !bOffsetFound )
449 sal_Int32 nX = 0, nY = 0;
451 bOk = rUnitConverter.convertMeasureToCore( nX, aToken );
452 if( bOk && aTokenEnum.getNextToken( aToken ) )
453 bOk = rUnitConverter.convertMeasureToCore( nY, aToken );
455 if( bOk )
457 if( nX < 0 )
459 if( nY < 0 )
461 rShadow.SetLocation( SvxShadowLocation::TopLeft );
463 else
465 rShadow.SetLocation( SvxShadowLocation::BottomLeft );
468 else
470 if( nY < 0 )
472 rShadow.SetLocation( SvxShadowLocation::TopRight );
474 else
476 rShadow.SetLocation( SvxShadowLocation::BottomRight );
480 if( nX < 0 ) nX *= -1;
481 if( nY < 0 ) nY *= -1;
483 rShadow.SetWidth( static_cast< sal_uInt16 >( (nX + nY) >> 1 ) );
488 if( bOk && ( bColorFound || bOffsetFound ) )
490 rShadow.SetColor(aColor);
492 else
493 bOk = false;
495 break;
497 case RES_BOX:
499 SvxBoxItem& rBox = dynamic_cast<SvxBoxItem&>(rItem);
501 // copy SvxBorderLines
502 BoxHolder aBoxes(rBox);
504 sal_Int32 nTemp;
506 switch( nMemberId )
508 case ALL_BORDER_PADDING:
509 case LEFT_BORDER_PADDING:
510 case RIGHT_BORDER_PADDING:
511 case TOP_BORDER_PADDING:
512 case BOTTOM_BORDER_PADDING:
513 if (!rUnitConverter.convertMeasureToCore( nTemp, rValue,
514 0, 0xffff ))
516 return false;
519 if( nMemberId == LEFT_BORDER_PADDING ||
520 nMemberId == ALL_BORDER_PADDING )
521 rBox.SetDistance( o3tl::narrowing<sal_uInt16>(nTemp), SvxBoxItemLine::LEFT );
522 if( nMemberId == RIGHT_BORDER_PADDING ||
523 nMemberId == ALL_BORDER_PADDING )
524 rBox.SetDistance( o3tl::narrowing<sal_uInt16>(nTemp), SvxBoxItemLine::RIGHT );
525 if( nMemberId == TOP_BORDER_PADDING ||
526 nMemberId == ALL_BORDER_PADDING )
527 rBox.SetDistance( o3tl::narrowing<sal_uInt16>(nTemp), SvxBoxItemLine::TOP );
528 if( nMemberId == BOTTOM_BORDER_PADDING ||
529 nMemberId == ALL_BORDER_PADDING )
530 rBox.SetDistance( o3tl::narrowing<sal_uInt16>(nTemp), SvxBoxItemLine::BOTTOM);
531 break;
533 case ALL_BORDER:
534 case LEFT_BORDER:
535 case RIGHT_BORDER:
536 case TOP_BORDER:
537 case BOTTOM_BORDER:
539 bool bHasStyle = false;
540 bool bHasWidth = false;
541 bool bHasColor = false;
543 sal_uInt16 nStyle = USHRT_MAX;
544 sal_uInt16 nWidth = 0;
545 sal_uInt16 nNamedWidth = USHRT_MAX;
547 Color aColor( COL_BLACK );
549 if( !sw_frmitems_parseXMLBorder( rValue, rUnitConverter,
550 bHasStyle, nStyle,
551 bHasWidth, nWidth, nNamedWidth,
552 bHasColor, aColor ) )
553 return false;
555 if( TOP_BORDER == nMemberId || ALL_BORDER == nMemberId )
556 sw_frmitems_setXMLBorder( aBoxes.pTop,
557 bHasStyle, nStyle,
558 bHasWidth, nWidth, nNamedWidth,
559 bHasColor, aColor );
561 if( BOTTOM_BORDER == nMemberId || ALL_BORDER == nMemberId )
562 sw_frmitems_setXMLBorder( aBoxes.pBottom,
563 bHasStyle, nStyle,
564 bHasWidth, nWidth, nNamedWidth,
565 bHasColor, aColor );
567 if( LEFT_BORDER == nMemberId || ALL_BORDER == nMemberId )
568 sw_frmitems_setXMLBorder( aBoxes.pLeft,
569 bHasStyle, nStyle,
570 bHasWidth, nWidth, nNamedWidth,
571 bHasColor, aColor );
573 if( RIGHT_BORDER == nMemberId || ALL_BORDER == nMemberId )
574 sw_frmitems_setXMLBorder( aBoxes.pRight,
575 bHasStyle, nStyle,
576 bHasWidth, nWidth, nNamedWidth,
577 bHasColor, aColor );
579 break;
580 case ALL_BORDER_LINE_WIDTH:
581 case LEFT_BORDER_LINE_WIDTH:
582 case RIGHT_BORDER_LINE_WIDTH:
583 case TOP_BORDER_LINE_WIDTH:
584 case BOTTOM_BORDER_LINE_WIDTH:
586 SvXMLTokenEnumerator aTokenEnum( rValue );
588 sal_Int32 nInWidth, nDistance, nOutWidth;
590 std::u16string_view aToken;
591 if( !aTokenEnum.getNextToken( aToken ) )
592 return false;
594 if (!rUnitConverter.convertMeasureToCore(nInWidth, aToken))
595 return false;
597 if( !aTokenEnum.getNextToken( aToken ) )
598 return false;
600 if (!rUnitConverter.convertMeasureToCore(nDistance, aToken))
601 return false;
603 if( !aTokenEnum.getNextToken( aToken ) )
604 return false;
606 if (!rUnitConverter.convertMeasureToCore(nOutWidth, aToken))
607 return false;
609 // #i61946: accept line style even it's not part of our "normal" set of line styles
610 sal_uInt16 nWidth = 0;
612 if( TOP_BORDER_LINE_WIDTH == nMemberId ||
613 ALL_BORDER_LINE_WIDTH == nMemberId )
614 sw_frmitems_setXMLBorder( aBoxes.pTop, nWidth,
615 static_cast< sal_uInt16 >( nOutWidth ),
616 static_cast< sal_uInt16 >( nInWidth ),
617 static_cast< sal_uInt16 >( nDistance ) );
619 if( BOTTOM_BORDER_LINE_WIDTH == nMemberId ||
620 ALL_BORDER_LINE_WIDTH == nMemberId )
621 sw_frmitems_setXMLBorder( aBoxes.pBottom, nWidth,
622 static_cast< sal_uInt16 >( nOutWidth ),
623 static_cast< sal_uInt16 >( nInWidth ),
624 static_cast< sal_uInt16 >( nDistance ) );
626 if( LEFT_BORDER_LINE_WIDTH == nMemberId ||
627 ALL_BORDER_LINE_WIDTH == nMemberId )
628 sw_frmitems_setXMLBorder( aBoxes.pLeft, nWidth,
629 static_cast< sal_uInt16 >( nOutWidth ),
630 static_cast< sal_uInt16 >( nInWidth ),
631 static_cast< sal_uInt16 >( nDistance ) );
633 if( RIGHT_BORDER_LINE_WIDTH == nMemberId ||
634 ALL_BORDER_LINE_WIDTH == nMemberId )
635 sw_frmitems_setXMLBorder( aBoxes.pRight, nWidth,
636 static_cast< sal_uInt16 >( nOutWidth ),
637 static_cast< sal_uInt16 >( nInWidth ),
638 static_cast< sal_uInt16 >( nDistance ) );
640 break;
643 rBox.SetLine( aBoxes.pTop.get(), SvxBoxItemLine::TOP );
644 rBox.SetLine( aBoxes.pBottom.get(), SvxBoxItemLine::BOTTOM );
645 rBox.SetLine( aBoxes.pLeft.get(), SvxBoxItemLine::LEFT );
646 rBox.SetLine( aBoxes.pRight.get(), SvxBoxItemLine::RIGHT );
648 bOk = true;
650 break;
652 case RES_BREAK:
654 SvxFormatBreakItem& rFormatBreak = dynamic_cast<SvxFormatBreakItem&>(rItem);
655 sal_uInt16 eEnum{};
657 if( !SvXMLUnitConverter::convertEnum( eEnum, rValue, psXML_BreakType ) )
658 return false;
660 if( eEnum == 0 )
662 rFormatBreak.SetValue( SvxBreak::NONE );
663 bOk = true;
665 else
667 switch( nMemberId )
669 case MID_BREAK_BEFORE:
670 rFormatBreak.SetValue( eEnum == 1 ?
671 SvxBreak::ColumnBefore :
672 SvxBreak::PageBefore );
673 break;
674 case MID_BREAK_AFTER:
675 rFormatBreak.SetValue( eEnum == 1 ?
676 SvxBreak::ColumnAfter :
677 SvxBreak::PageAfter );
678 break;
680 bOk = true;
683 break;
685 case RES_KEEP:
687 SvxFormatKeepItem& rFormatKeep = dynamic_cast<SvxFormatKeepItem&>(rItem);
689 if( IsXMLToken( rValue, XML_ALWAYS ) ||
690 IsXMLToken( rValue, XML_TRUE ) )
692 rFormatKeep.SetValue( true );
693 bOk = true;
695 else if( IsXMLToken( rValue, XML_AUTO ) ||
696 IsXMLToken( rValue, XML_FALSE ) )
698 rFormatKeep.SetValue( false );
699 bOk = true;
702 break;
704 case RES_BACKGROUND:
706 SvxBrushItem& rBrush = dynamic_cast<SvxBrushItem&>(rItem);
708 Color aTempColor;
709 switch( nMemberId )
711 case MID_BACK_COLOR:
712 if( IsXMLToken( rValue, XML_TRANSPARENT ) )
714 rBrush.GetColor().SetAlpha(0);
715 bOk = true;
717 else if (::sax::Converter::convertColor(aTempColor, rValue))
719 aTempColor.SetAlpha(255);
720 rBrush.SetColor( aTempColor );
721 bOk = true;
723 break;
725 case MID_GRAPHIC_REPEAT:
727 SvxGraphicPosition eGraphicPos = rBrush.GetGraphicPos();
728 SvxGraphicPosition nPos = GPOS_NONE;
729 if( SvXMLUnitConverter::convertEnum( nPos, rValue,
730 psXML_BrushRepeat ) )
732 if( GPOS_MM != nPos || GPOS_NONE == eGraphicPos ||
733 GPOS_AREA == eGraphicPos || GPOS_TILED == eGraphicPos )
734 rBrush.SetGraphicPos( nPos );
735 bOk = true;
738 break;
740 case MID_GRAPHIC_POSITION:
742 SvxGraphicPosition ePos = GPOS_NONE, eTmp;
743 SvxGraphicPosition nTmp;
744 SvXMLTokenEnumerator aTokenEnum( rValue );
745 std::u16string_view aToken;
746 bool bHori = false, bVert = false;
747 bOk = true;
748 while( bOk && aTokenEnum.getNextToken( aToken ) )
750 if( bHori && bVert )
752 bOk = false;
754 else if( std::u16string_view::npos != aToken.find( '%' ) )
756 sal_Int32 nPrc = 50;
757 if (::sax::Converter::convertPercent(nPrc, aToken))
759 if( !bHori )
761 ePos = nPrc < 25 ? GPOS_LT :
762 (nPrc < 75 ? GPOS_MM : GPOS_RB);
763 bHori = true;
765 else
767 eTmp = nPrc < 25 ? GPOS_LT:
768 (nPrc < 75 ? GPOS_LM : GPOS_LB);
769 sw_frmitems_MergeXMLVertPos( ePos, eTmp );
770 bVert = true;
773 else
775 // wrong percentage
776 bOk = false;
779 else if( IsXMLToken( aToken, XML_CENTER ) )
781 if( bHori )
782 sw_frmitems_MergeXMLVertPos( ePos, GPOS_MM );
783 else if ( bVert )
784 sw_frmitems_MergeXMLHoriPos( ePos, GPOS_MM );
785 else
786 ePos = GPOS_MM;
788 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
789 psXML_BrushHoriPos ) )
791 if( bVert )
792 sw_frmitems_MergeXMLHoriPos(
793 ePos, nTmp );
794 else if( !bHori )
795 ePos = nTmp;
796 else
797 bOk = false;
798 bHori = true;
800 else if( SvXMLUnitConverter::convertEnum( nTmp, aToken,
801 psXML_BrushVertPos ) )
803 if( bHori )
804 sw_frmitems_MergeXMLVertPos(
805 ePos, nTmp );
806 else if( !bVert )
807 ePos = nTmp;
808 else
809 bOk = false;
810 bVert = true;
812 else
814 bOk = false;
818 if( GPOS_NONE == ePos ) bOk = false;
819 if( bOk )
820 rBrush.SetGraphicPos( ePos );
822 break;
824 case MID_GRAPHIC_FILTER:
825 rBrush.SetGraphicFilter( rValue );
826 bOk = true;
827 break;
830 break;
832 case RES_PAGEDESC:
834 SwFormatPageDesc& rPageDesc = dynamic_cast<SwFormatPageDesc&>(rItem);
836 if( MID_PAGEDESC_PAGENUMOFFSET==nMemberId )
838 sal_Int32 nVal;
839 bOk = ::sax::Converter::convertNumber(
840 nVal, rValue, 0, USHRT_MAX);
841 // i#114163 tdf#77111: OOo < 3.3 had a bug where it wrote
842 // "auto" as "0" for tables - now that we support a real offset
843 // 0, this fake "0" MUST NOT be imported as offset 0!
844 if( bOk && nVal > 0 )
845 rPageDesc.SetNumOffset( o3tl::narrowing<sal_uInt16>(nVal) );
848 break;
850 case RES_LAYOUT_SPLIT:
851 case RES_ROW_SPLIT:
853 SfxBoolItem& rSplit = dynamic_cast<SfxBoolItem&>(rItem);
855 if( IsXMLToken( rValue, XML_AUTO ) ||
856 IsXMLToken( rValue, XML_TRUE ) )
858 rSplit.SetValue( true );
859 bOk = true;
861 else if( IsXMLToken( rValue, XML_ALWAYS ) ||
862 IsXMLToken( rValue, XML_FALSE ) )
864 rSplit.SetValue( false );
865 bOk = true;
868 break;
870 case RES_PRINT:
872 SfxBoolItem& rHasTextChangesOnly = dynamic_cast<SfxBoolItem&>(rItem);
874 if( IsXMLToken( rValue, XML_TRUE ) )
876 rHasTextChangesOnly.SetValue( true );
877 bOk = true;
879 else if( IsXMLToken( rValue, XML_FALSE ) )
881 rHasTextChangesOnly.SetValue( false );
882 bOk = true;
885 break;
887 case RES_HORI_ORIENT:
889 SwFormatHoriOrient& rHoriOrient = dynamic_cast<SwFormatHoriOrient&>(rItem);
891 sal_Int16 nValue;
892 bOk = SvXMLUnitConverter::convertEnum( nValue, rValue,
893 aXMLTableAlignMap );
894 if( bOk )
895 rHoriOrient.SetHoriOrient( nValue );
897 break;
899 case RES_VERT_ORIENT:
901 SwFormatVertOrient& rVertOrient = dynamic_cast<SwFormatVertOrient&>(rItem);
903 sal_Int16 nValue;
904 bOk = SvXMLUnitConverter::convertEnum( nValue, rValue,
905 aXMLTableVAlignMap );
906 if( bOk )
907 rVertOrient.SetVertOrient( nValue );
908 //#i8855# text::VertOrientation::NONE is stored as empty string and should be applied here
909 else if(rValue.isEmpty())
911 rVertOrient.SetVertOrient( text::VertOrientation::NONE );
912 bOk = true;
915 break;
917 case RES_FRM_SIZE:
919 SwFormatFrameSize& rFrameSize = dynamic_cast<SwFormatFrameSize&>(rItem);
921 bool bSetHeight = false;
922 bool bSetWidth = false;
923 bool bSetSizeType = false;
924 SwFrameSize eSizeType = SwFrameSize::Variable;
925 sal_Int32 nMin = MINLAY;
927 switch( nMemberId )
929 case MID_FRMSIZE_REL_WIDTH:
931 sal_Int32 nValue;
932 bOk = ::sax::Converter::convertPercent( nValue, rValue );
933 if( bOk )
935 if( nValue < 1 )
936 nValue = 1;
937 else if( nValue > 100 )
938 nValue = 100;
940 rFrameSize.SetWidthPercent( static_cast<sal_Int8>(nValue) );
943 break;
944 case MID_FRMSIZE_WIDTH:
945 bSetWidth = true;
946 break;
947 case MID_FRMSIZE_MIN_HEIGHT:
948 eSizeType = SwFrameSize::Minimum;
949 bSetHeight = true;
950 nMin = 1;
951 bSetSizeType = true;
952 break;
953 case MID_FRMSIZE_FIX_HEIGHT:
954 eSizeType = SwFrameSize::Fixed;
955 bSetHeight = true;
956 nMin = 1;
957 bSetSizeType = true;
958 break;
959 case MID_FRMSIZE_COL_WIDTH:
960 eSizeType = SwFrameSize::Fixed;
961 bSetWidth = true;
962 bSetSizeType = true;
963 break;
964 case MID_FRMSIZE_REL_COL_WIDTH:
966 sal_Int32 nPos = rValue.indexOf( '*' );
967 if( -1 != nPos )
969 sal_Int32 nValue = rValue.toInt32();
970 if( nValue < MINLAY )
971 nValue = MINLAY;
972 else if( nValue > SAL_MAX_UINT16 )
973 nValue = SAL_MAX_UINT16;
975 rFrameSize.SetWidth( o3tl::narrowing<sal_uInt16>(nValue) );
976 rFrameSize.SetHeightSizeType( SwFrameSize::Variable );
977 bOk = true;
980 break;
983 if( bSetHeight || bSetWidth )
985 sal_Int32 nValue;
986 bOk = rUnitConverter.convertMeasureToCore(nValue, rValue, nMin,
987 USHRT_MAX );
988 if( bOk )
990 if( bSetWidth )
991 rFrameSize.SetWidth( o3tl::narrowing<sal_uInt16>(nValue) );
992 if( bSetHeight )
993 rFrameSize.SetHeight( o3tl::narrowing<sal_uInt16>(nValue) );
994 if( bSetSizeType )
995 rFrameSize.SetHeightSizeType( eSizeType );
999 break;
1001 case RES_FRAMEDIR:
1003 if (IsXMLToken(rValue, XML_BT_LR))
1005 // Read bt-lr from the extension namespace, handle other values
1006 // below.
1007 Any aAny;
1008 aAny <<= static_cast<sal_uInt16>(SvxFrameDirection::Vertical_LR_BT);
1009 bOk = rItem.PutValue(aAny, 0);
1011 else if (IsXMLToken(rValue, XML_TB_RL90))
1013 // Read tb-rl90 from the extension namespace.
1014 Any aAny;
1015 aAny <<= static_cast<sal_uInt16>(SvxFrameDirection::Vertical_RL_TB90);
1016 bOk = rItem.PutValue(aAny, 0);
1018 else
1020 std::unique_ptr<XMLPropertyHandler> pWritingModeHandler =
1021 XMLPropertyHandlerFactory::CreatePropertyHandler(
1022 XML_TYPE_TEXT_WRITING_MODE_WITH_DEFAULT );
1023 Any aAny;
1024 bOk = pWritingModeHandler->importXML( rValue, aAny,
1025 rUnitConverter );
1026 if( bOk )
1027 bOk = rItem.PutValue( aAny, 0 );
1030 break;
1032 case RES_COLLAPSING_BORDERS:
1034 SfxBoolItem& rBorders = dynamic_cast<SfxBoolItem&>(rItem);
1036 if( IsXMLToken( rValue, XML_COLLAPSING ) )
1038 rBorders.SetValue(true);
1039 bOk = true;
1041 else if( IsXMLToken( rValue, XML_SEPARATING ) )
1043 rBorders.SetValue(false);
1044 bOk = true;
1046 else
1047 bOk = false;
1049 break;
1051 default:
1052 OSL_FAIL("Item not implemented!");
1053 break;
1056 return bOk;
1059 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */