LibreOffice Module xmloff (master)  1
xmluconv.cxx
Go to the documentation of this file.
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 <sal/config.h>
21 
22 #include <string_view>
23 
24 #include <xmloff/xmluconv.hxx>
25 
26 #include <com/sun/star/util/DateTime.hpp>
27 #include <com/sun/star/util/Date.hpp>
28 #include <rtl/ustrbuf.hxx>
29 #include <osl/diagnose.h>
30 #include <sal/log.hxx>
31 #include <xmloff/xmlement.hxx>
32 #include <xmloff/xmltoken.hxx>
33 #include <rtl/math.hxx>
34 
35 #include <tools/date.hxx>
36 #include <tools/time.hxx>
37 #include <tools/fldunit.hxx>
38 
39 #include <com/sun/star/drawing/Position3D.hpp>
40 #include <com/sun/star/frame/XModel.hpp>
41 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
42 #include <com/sun/star/style/NumberingType.hpp>
43 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
44 #include <com/sun/star/text/XDefaultNumberingProvider.hpp>
45 #include <com/sun/star/text/XNumberingTypeInfo.hpp>
46 #include <com/sun/star/i18n/CharacterClassification.hpp>
47 #include <com/sun/star/i18n/UnicodeType.hpp>
49 
50 #include <sax/tools/converter.hxx>
51 
52 
53 using namespace com::sun::star;
54 using namespace com::sun::star::uno;
55 using namespace com::sun::star::lang;
56 using namespace com::sun::star::text;
57 using namespace com::sun::star::style;
58 using namespace ::com::sun::star::i18n;
59 using namespace ::xmloff::token;
60 
61 
63 #define XML_NULLDATE "NullDate"
64 
66 {
67  sal_Int16 m_eCoreMeasureUnit; /*css::util::MeasureUnit*/
68  sal_Int16 m_eXMLMeasureUnit; /*css::util::MeasureUnit*/
69  util::Date m_aNullDate;
70  mutable uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo;
71  mutable uno::Reference< i18n::XCharacterClassification > m_xCharClass;
72  uno::Reference< uno::XComponentContext > m_xContext;
73 
74  Impl(uno::Reference<uno::XComponentContext> const& xContext,
75  sal_Int16 const eCoreMeasureUnit,
76  sal_Int16 const eXMLMeasureUnit)
77  : m_eCoreMeasureUnit(eCoreMeasureUnit)
78  , m_eXMLMeasureUnit(eXMLMeasureUnit)
79  , m_aNullDate(30, 12, 1899)
80  , m_xContext(xContext)
81  {
82  OSL_ENSURE( m_xContext.is(), "got no service manager" );
83  }
84 
85  void createNumTypeInfo() const;
86 };
87 
88 
90 {
91  Reference<XDefaultNumberingProvider> xDefNum = DefaultNumberingProvider::create(m_xContext);
92  m_xNumTypeInfo.set(xDefNum, uno::UNO_QUERY);
93 }
94 
95 const uno::Reference< text::XNumberingTypeInfo >&
97 {
98  if (!m_pImpl->m_xNumTypeInfo.is())
99  {
100  m_pImpl->createNumTypeInfo();
101  }
102  return m_pImpl->m_xNumTypeInfo;
103 }
104 
105 void SvXMLUnitConverter::SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit/*css::util::MeasureUnit*/)
106 {
107  m_pImpl->m_eCoreMeasureUnit = eCoreMeasureUnit;
108 }
109 
110 void SvXMLUnitConverter::SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit/*css::util::MeasureUnit*/)
111 {
112  m_pImpl->m_eXMLMeasureUnit = eXMLMeasureUnit;
113 }
114 
116 {
117  return m_pImpl->m_eXMLMeasureUnit;
118 }
119 
126  const uno::Reference<uno::XComponentContext>& xContext,
127  sal_Int16 const eCoreMeasureUnit,
128  sal_Int16 const eXMLMeasureUnit)
129 : m_pImpl(new Impl(xContext, eCoreMeasureUnit, eXMLMeasureUnit))
130 {
131 }
132 
134 {
135 }
136 
138 {
139  sal_Int16 eUnit = util::MeasureUnit::INCH;
140  switch( nFieldUnit )
141  {
142  case FieldUnit::MM:
143  eUnit = util::MeasureUnit::MM;
144  break;
145  case FieldUnit::CM:
146  case FieldUnit::M:
147  case FieldUnit::KM:
148  eUnit = util::MeasureUnit::CM;
149  break;
150  case FieldUnit::TWIP:
151  eUnit = util::MeasureUnit::TWIP;
152  break;
153  case FieldUnit::POINT:
154  case FieldUnit::PICA:
155  eUnit = util::MeasureUnit::POINT;
156  break;
157  case FieldUnit::MM_100TH:
158  eUnit = util::MeasureUnit::MM_100TH;
159  break;
160  case FieldUnit::INCH:
161  eUnit = util::MeasureUnit::INCH;
162  break;
163  default:
164  assert(false);
165  break;
166  }
167  return eUnit;
168 }
169 
172  const OUString& rString,
173  sal_Int32 nMin, sal_Int32 nMax ) const
174 {
175  return ::sax::Converter::convertMeasure( nValue, rString,
176  m_pImpl->m_eCoreMeasureUnit,
177  nMin, nMax );
178 }
179 
181 void SvXMLUnitConverter::convertMeasureToXML( OUStringBuffer& rString,
182  sal_Int32 nMeasure ) const
183 {
184  ::sax::Converter::convertMeasure( rString, nMeasure,
185  m_pImpl->m_eCoreMeasureUnit,
186  m_pImpl->m_eXMLMeasureUnit );
187 }
188 
190 OUString SvXMLUnitConverter::convertMeasureToXML( sal_Int32 nMeasure ) const
191 {
192  OUStringBuffer s;
194  m_pImpl->m_eCoreMeasureUnit,
195  m_pImpl->m_eXMLMeasureUnit );
196  return s.makeStringAndClear();
197 }
198 
202 bool SvXMLUnitConverter::convertEnumImpl( sal_uInt16& rEnum,
203  const OUString& rValue,
205 {
206  while( pMap->GetName() )
207  {
208  if( rValue.equalsAsciiL( pMap->GetName(), pMap->GetNameLength() ) )
209  {
210  rEnum = pMap->GetValue();
211  return true;
212  }
213  ++pMap;
214  }
215 
216  return false;
217 }
218 
222  sal_uInt16& rEnum,
223  const OUString& rValue,
224  const SvXMLEnumMapEntry<sal_uInt16> *pMap )
225 {
226  while( pMap->GetToken() != XML_TOKEN_INVALID )
227  {
228  if( IsXMLToken( rValue, pMap->GetToken() ) )
229  {
230  rEnum = pMap->GetValue();
231  return true;
232  }
233  ++pMap;
234  }
235  return false;
236 }
237 
243  OUStringBuffer& rBuffer,
244  sal_uInt16 nValue,
245  const SvXMLEnumMapEntry<sal_uInt16> *pMap,
246  enum XMLTokenEnum eDefault)
247 {
248  enum XMLTokenEnum eTok = eDefault;
249 
250  while( pMap->GetToken() != XML_TOKEN_INVALID )
251  {
252  if( pMap->GetValue() == nValue )
253  {
254  eTok = pMap->GetToken();
255  break;
256  }
257  ++pMap;
258  }
259 
260  // the map may have contained XML_TOKEN_INVALID
261  if( eTok == XML_TOKEN_INVALID )
262  eTok = eDefault;
263 
264  if( eTok != XML_TOKEN_INVALID )
265  rBuffer.append( GetXMLToken(eTok) );
266 
267  return (eTok != XML_TOKEN_INVALID);
268 }
269 
270 static int lcl_gethex( int nChar )
271 {
272  if( nChar >= '0' && nChar <= '9' )
273  return nChar - '0';
274  else if( nChar >= 'a' && nChar <= 'f' )
275  return nChar - 'a' + 10;
276  else if( nChar >= 'A' && nChar <= 'F' )
277  return nChar - 'A' + 10;
278  else
279  return 0;
280 }
281 
282 const char aHexTab[] = "0123456789abcdef";
283 
284 
286 void SvXMLUnitConverter::convertDouble(OUStringBuffer& rBuffer,
287  double fNumber) const
288 {
289  ::sax::Converter::convertDouble(rBuffer, fNumber,
290  true/*bWriteUnits*/, m_pImpl->m_eCoreMeasureUnit, m_pImpl->m_eXMLMeasureUnit);
291 }
292 
295  const OUString& rString) const
296 {
297  sal_Int16 const eSrcUnit = ::sax::Converter::GetUnitFromString(
298  rString, m_pImpl->m_eCoreMeasureUnit);
299 
300  return ::sax::Converter::convertDouble(rValue, rString,
301  eSrcUnit, m_pImpl->m_eCoreMeasureUnit);
302 }
303 
305 bool SvXMLUnitConverter::setNullDate(const css::uno::Reference <css::frame::XModel>& xModel)
306 {
307  css::uno::Reference <css::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, css::uno::UNO_QUERY);
308  if (xNumberFormatsSupplier.is())
309  {
310  const css::uno::Reference <css::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
311  return xPropertySet.is() && (xPropertySet->getPropertyValue(XML_NULLDATE) >>= m_pImpl->m_aNullDate);
312  }
313  return false;
314 }
315 
317 void SvXMLUnitConverter::convertDateTime(OUStringBuffer& rBuffer,
318  const double& fDateTime, bool const bAddTimeIf0AM)
319 {
320  convertDateTime(rBuffer, fDateTime, m_pImpl->m_aNullDate, bAddTimeIf0AM);
321 }
322 
324 bool SvXMLUnitConverter::convertDateTime(double& fDateTime,
325  const OUString& rString)
326 {
327  return convertDateTime(fDateTime, rString, m_pImpl->m_aNullDate);
328 }
329 
331 void SvXMLUnitConverter::convertDateTime( OUStringBuffer& rBuffer,
332  const double& fDateTime,
333  const css::util::Date& aTempNullDate,
334  bool bAddTimeIf0AM )
335 {
336  double fValue = fDateTime;
337  const sal_Int32 nDays = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
338  Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
339  aDate.AddDays( nDays);
340  fValue -= nDays;
341  const bool bHasTime = (fValue > 0.0);
342 
343  sal_Int16 nTempYear = aDate.GetYear();
344  assert(nTempYear != 0);
345  if (nTempYear < 0)
346  {
347  rBuffer.append( '-');
348  nTempYear = -nTempYear;
349  }
350  if (nTempYear < 1000)
351  rBuffer.append( '0');
352  if (nTempYear < 100)
353  rBuffer.append( '0');
354  if (nTempYear < 10)
355  rBuffer.append( '0');
356  rBuffer.append( sal_Int32( nTempYear));
357  rBuffer.append( '-');
358  sal_uInt16 nTemp = aDate.GetMonth();
359  assert(1 <= nTemp && nTemp <= 12);
360  if (nTemp < 10)
361  rBuffer.append( '0');
362  rBuffer.append( sal_Int32( nTemp));
363  rBuffer.append( '-');
364  nTemp = aDate.GetDay();
365  assert(1 <= nTemp && nTemp <= 31);
366  if (nTemp < 10)
367  rBuffer.append( '0');
368  rBuffer.append( sal_Int32( nTemp));
369  if (!(bHasTime || bAddTimeIf0AM))
370  return;
371 
372  double fCount;
373  if (nDays > 0)
374  fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays))) + 1;
375  else if (nDays < 0)
376  fCount = ::rtl::math::approxFloor (log10(static_cast<double>(nDays * -1))) + 1;
377  else
378  fCount = 0.0;
379  const int nDigits = sal_Int16(fCount) + 4; // +4 for *86400 in seconds
380  const int nFractionDecimals = std::max( XML_MAXDIGITSCOUNT_TIME - nDigits, 0);
381 
382  sal_uInt16 nHour, nMinute, nSecond;
383  double fFractionOfSecond;
384  // Pass the original date+time value for proper scaling and rounding.
385  tools::Time::GetClock( fDateTime, nHour, nMinute, nSecond, fFractionOfSecond, nFractionDecimals);
386 
387  rBuffer.append( 'T');
388  if (nHour < 10)
389  rBuffer.append( '0');
390  rBuffer.append( sal_Int32( nHour));
391  rBuffer.append( ':');
392  if (nMinute < 10)
393  rBuffer.append( '0');
394  rBuffer.append( sal_Int32( nMinute));
395  rBuffer.append( ':');
396  if (nSecond < 10)
397  rBuffer.append( '0');
398  rBuffer.append( sal_Int32( nSecond));
399  if (!nFractionDecimals)
400  return;
401 
402  // nFractionDecimals+1 to not round up what GetClock() carefully
403  // truncated.
404  OUString aFraction( ::rtl::math::doubleToUString( fFractionOfSecond,
405  rtl_math_StringFormat_F,
406  nFractionDecimals + 1, '.', true));
407  const sal_Int32 nLen = aFraction.getLength();
408  if ( nLen > 2 )
409  {
410  // Truncate nFractionDecimals+1 digit if it was not rounded to zero.
411  const sal_Int32 nCount = nLen - 2 - static_cast<int>(nLen > nFractionDecimals + 2);
412  rBuffer.append( '.');
413  rBuffer.append( std::u16string_view(aFraction).substr(2, nCount)); // strip 0.
414  }
415 }
416 
418 bool SvXMLUnitConverter::convertDateTime( double& fDateTime,
419  const OUString& rString, const css::util::Date& aTempNullDate)
420 {
421  css::util::DateTime aDateTime;
422  bool bSuccess = ::sax::Converter::parseDateTime(aDateTime, rString);
423 
424  if (bSuccess)
425  {
426  const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
427  const Date aTempDate(aDateTime.Day, aDateTime.Month, aDateTime.Year);
428  const sal_Int32 nTage = aTempDate - aTmpNullDate;
429  double fTempDateTime = nTage;
430  double Hour = aDateTime.Hours;
431  double Min = aDateTime.Minutes;
432  double Sec = aDateTime.Seconds;
433  double NanoSec = aDateTime.NanoSeconds;
434  fTempDateTime += Hour / ::tools::Time::hourPerDay;
435  fTempDateTime += Min / ::tools::Time::minutePerDay;
436  fTempDateTime += Sec / ::tools::Time::secondPerDay;
437  fTempDateTime += NanoSec / ::tools::Time::nanoSecPerDay;
438  fDateTime = fTempDateTime;
439  }
440  return bSuccess;
441 }
442 
443 
444 SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeparator /* = ' ' */ )
445 : maTokenString( rString ), mnNextTokenPos(0), mcSeparator( cSeparator )
446 {
447 }
448 
449 bool SvXMLTokenEnumerator::getNextToken( OUString& rToken )
450 {
451  if( -1 == mnNextTokenPos )
452  return false;
453 
454  int nTokenEndPos = maTokenString.indexOf( mcSeparator, mnNextTokenPos );
455  if( nTokenEndPos != -1 )
456  {
457  rToken = maTokenString.copy( mnNextTokenPos,
458  nTokenEndPos - mnNextTokenPos );
459  mnNextTokenPos = nTokenEndPos + 1;
460 
461  // if the mnNextTokenPos is at the end of the string, we have
462  // to deliver an empty token
463  if( mnNextTokenPos > maTokenString.getLength() )
464  mnNextTokenPos = -1;
465  }
466  else
467  {
468  rToken = maTokenString.copy( mnNextTokenPos );
469  mnNextTokenPos = -1;
470  }
471 
472  return true;
473 }
474 
475 static bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
476 {
477  if(_sValue.isEmpty() || _sValue[0] != '(')
478  return false;
479 
480  sal_Int32 nPos(1);
481  sal_Int32 nFound = _sValue.indexOf(' ', nPos);
482 
483  if(nFound == -1 || nFound <= nPos)
484  return false;
485 
486  _rContentX = _sValue.copy(nPos, nFound - nPos);
487 
488  nPos = nFound + 1;
489  nFound = _sValue.indexOf(' ', nPos);
490 
491  if(nFound == -1 || nFound <= nPos)
492  return false;
493 
494  _rContentY = _sValue.copy(nPos, nFound - nPos);
495 
496  nPos = nFound + 1;
497  nFound = _sValue.indexOf(')', nPos);
498 
499  if(nFound == -1 || nFound <= nPos)
500  return false;
501 
502  _rContentZ = _sValue.copy(nPos, nFound - nPos);
503  return true;
504 
505 }
508 {
509  OUString aContentX,aContentY,aContentZ;
510  if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
511  return false;
512 
513  rtl_math_ConversionStatus eStatus;
514 
515  rVector.setX(::rtl::math::stringToDouble(aContentX, '.',
516  ',', &eStatus));
517 
518  if( eStatus != rtl_math_ConversionStatus_Ok )
519  return false;
520 
521  rVector.setY(::rtl::math::stringToDouble(aContentY, '.',
522  ',', &eStatus));
523 
524  if( eStatus != rtl_math_ConversionStatus_Ok )
525  return false;
526 
527  rVector.setZ(::rtl::math::stringToDouble(aContentZ, '.',
528  ',', &eStatus));
529 
530 
531  return ( eStatus == rtl_math_ConversionStatus_Ok );
532 }
533 
535 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
536 {
537  rBuffer.append('(');
538  ::sax::Converter::convertDouble(rBuffer, rVector.getX());
539  rBuffer.append(' ');
540  ::sax::Converter::convertDouble(rBuffer, rVector.getY());
541  rBuffer.append(' ');
542  ::sax::Converter::convertDouble(rBuffer, rVector.getZ());
543  rBuffer.append(')');
544 }
545 
547 bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition,
548  const OUString& rValue )
549 {
550  OUString aContentX,aContentY,aContentZ;
551  if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
552  return false;
553 
554  if ( !convertDouble( rPosition.PositionX, aContentX ) )
555  return false;
556  if ( !convertDouble( rPosition.PositionY, aContentY ) )
557  return false;
558  return convertDouble( rPosition.PositionZ, aContentZ );
559 }
560 
562 void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer,
563  const drawing::Position3D& rPosition )
564 {
565  rBuffer.append( '(' );
566  convertDouble( rBuffer, rPosition.PositionX );
567  rBuffer.append( ' ' );
568  convertDouble( rBuffer, rPosition.PositionY );
569  rBuffer.append( ' ' );
570  convertDouble( rBuffer, rPosition.PositionZ );
571  rBuffer.append( ')' );
572 }
573 
575  sal_Int16& rType,
576  const OUString& rNumFmt,
577  const OUString& rNumLetterSync,
578  bool bNumberNone ) const
579 {
580  bool bRet = true;
581  bool bExt = false;
582 
583  sal_Int32 nLen = rNumFmt.getLength();
584  if( 0 == nLen )
585  {
586  if( bNumberNone )
587  rType = NumberingType::NUMBER_NONE;
588  else
589  bRet = false;
590  }
591  else if( 1 == nLen )
592  {
593  switch( rNumFmt[0] )
594  {
595  case '1': rType = NumberingType::ARABIC; break;
596  case 'a': rType = NumberingType::CHARS_LOWER_LETTER; break;
597  case 'A': rType = NumberingType::CHARS_UPPER_LETTER; break;
598  case 'i': rType = NumberingType::ROMAN_LOWER; break;
599  case 'I': rType = NumberingType::ROMAN_UPPER; break;
600  default: bExt = true; break;
601  }
602  if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) )
603  {
604  switch( rType )
605  {
606  case NumberingType::CHARS_LOWER_LETTER:
607  rType = NumberingType::CHARS_LOWER_LETTER_N;
608  break;
609  case NumberingType::CHARS_UPPER_LETTER:
610  rType = NumberingType::CHARS_UPPER_LETTER_N;
611  break;
612  }
613  }
614  }
615  else
616  {
617  bExt = true;
618  }
619  if( bExt )
620  {
622  if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
623  {
624  rType = xInfo->getNumberingType( rNumFmt );
625  }
626  else
627  {
628  rType = NumberingType::ARABIC;
629  }
630  }
631 
632  return bRet;
633 }
634 
635 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
636  sal_Int16 nType ) const
637 {
638  enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
639  switch( nType )
640  {
641  case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break;
642  case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break;
643  case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break;
644  case NumberingType::ROMAN_LOWER: eFormat = XML_I; break;
645  case NumberingType::ARABIC: eFormat = XML_1; break;
646  case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break;
647  case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break;
648  case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break;
649 
650  case NumberingType::CHAR_SPECIAL:
651  case NumberingType::PAGE_DESCRIPTOR:
652  case NumberingType::BITMAP:
653  SAL_WARN_IF( eFormat == XML_TOKEN_INVALID, "xmloff", "invalid number format" );
654  break;
655  default:
656  break;
657  }
658 
659  if( eFormat != XML_TOKEN_INVALID )
660  {
661  rBuffer.append( GetXMLToken(eFormat) );
662  }
663  else
664  {
666  if( xInfo.is() )
667  rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
668  }
669 }
670 
671 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
672  sal_Int16 nType )
673 {
674  enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
675  switch( nType )
676  {
677  case NumberingType::CHARS_UPPER_LETTER:
678  case NumberingType::CHARS_LOWER_LETTER:
679  case NumberingType::ROMAN_UPPER:
680  case NumberingType::ROMAN_LOWER:
681  case NumberingType::ARABIC:
682  case NumberingType::NUMBER_NONE:
683  break;
684 
685  case NumberingType::CHARS_UPPER_LETTER_N:
686  case NumberingType::CHARS_LOWER_LETTER_N:
687  eSync = XML_TRUE;
688  break;
689 
690  case NumberingType::CHAR_SPECIAL:
691  case NumberingType::PAGE_DESCRIPTOR:
692  case NumberingType::BITMAP:
693  SAL_WARN_IF( eSync == XML_TOKEN_INVALID, "xmloff", "invalid number format" );
694  break;
695  }
696  if( eSync != XML_TOKEN_INVALID )
697  rBuffer.append( GetXMLToken(eSync) );
698 }
699 
700 void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps,
701  const uno::Reference<beans::XPropertySet>& aProperties)
702 {
703  uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
704  if (!xPropertySetInfo.is())
705  return;
706 
707  const uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
708  if (aProps.hasElements())
709  {
710  rProps.realloc(aProps.getLength());
711  beans::PropertyValue* pProps = rProps.getArray();
712  for (const auto& rProp : aProps)
713  {
714  pProps->Name = rProp.Name;
715  pProps->Value = aProperties->getPropertyValue(rProp.Name);
716  ++pProps;
717  }
718  }
719 }
720 
721 void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet> const & rProperties,
722  const uno::Sequence<beans::PropertyValue>& aProps)
723 {
724  if (aProps.hasElements())
725  {
726  uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
727  if (xPropertySetInfo.is())
728  {
729  for (const auto& rProp : aProps)
730  {
731  if (xPropertySetInfo->hasPropertyByName(rProp.Name))
732  rProperties->setPropertyValue(rProp.Name, rProp.Value);
733  }
734  }
735  }
736 }
737 
738 
740  const OUString& rName,
741  bool *pEncoded ) const
742 {
743  if( pEncoded )
744  *pEncoded = false;
745 
746  sal_Int32 nLen = rName.getLength();
747  OUStringBuffer aBuffer( nLen*2 );
748 
749  for( sal_Int32 i = 0; i < nLen; i++ )
750  {
751  sal_Unicode c = rName[i];
752  bool bValidChar = false;
753  if( c < 0x00ffU )
754  {
755  bValidChar =
756  (c >= 0x0041 && c <= 0x005a) ||
757  (c >= 0x0061 && c <= 0x007a) ||
758  (c >= 0x00c0 && c <= 0x00d6) ||
759  (c >= 0x00d8 && c <= 0x00f6) ||
760  (c >= 0x00f8 && c <= 0x00ff) ||
761  ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
762  c == 0x00b7 || c == '-' || c == '.') );
763  }
764  else
765  {
766  if( (c >= 0xf900U && c <= 0xfffeU) ||
767  (c >= 0x20ddU && c <= 0x20e0U))
768  {
769  bValidChar = false;
770  }
771  else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
772  c == 0x06e5 || c == 0x06e6 )
773  {
774  bValidChar = true;
775  }
776  else if( c == 0x0387 )
777  {
778  bValidChar = i > 0;
779  }
780  else
781  {
782  if (!m_pImpl->m_xCharClass.is())
783  {
784  m_pImpl->m_xCharClass = CharacterClassification::create( m_pImpl->m_xContext );
785  }
786  sal_Int16 nType = m_pImpl->m_xCharClass->getType(rName, i);
787 
788  switch( nType )
789  {
790  case UnicodeType::UPPERCASE_LETTER: // Lu
791  case UnicodeType::LOWERCASE_LETTER: // Ll
792  case UnicodeType::TITLECASE_LETTER: // Lt
793  case UnicodeType::OTHER_LETTER: // Lo
794  case UnicodeType::LETTER_NUMBER: // Nl
795  bValidChar = true;
796  break;
797  case UnicodeType::NON_SPACING_MARK: // Ms
798  case UnicodeType::ENCLOSING_MARK: // Me
799  case UnicodeType::COMBINING_SPACING_MARK: //Mc
800  case UnicodeType::MODIFIER_LETTER: // Lm
801  case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
802  bValidChar = i > 0;
803  break;
804  }
805  }
806  }
807  if( bValidChar )
808  {
809  aBuffer.append( c );
810  }
811  else
812  {
813  aBuffer.append( '_' );
814  if( c > 0x0fff )
815  aBuffer.append( static_cast< sal_Unicode >(
816  aHexTab[ (c >> 12) & 0x0f ] ) );
817  if( c > 0x00ff )
818  aBuffer.append( static_cast< sal_Unicode >(
819  aHexTab[ (c >> 8) & 0x0f ] ) );
820  if( c > 0x000f )
821  aBuffer.append( static_cast< sal_Unicode >(
822  aHexTab[ (c >> 4) & 0x0f ] ) );
823  aBuffer.append( static_cast< sal_Unicode >(
824  aHexTab[ c & 0x0f ] ) );
825  aBuffer.append( '_' );
826  if( pEncoded )
827  *pEncoded = true;
828  }
829  }
830 
831  // check for length
832  if( aBuffer.getLength() > ((1<<15)-1) )
833  {
834  aBuffer = rName;
835  if( pEncoded )
836  *pEncoded = false;
837  }
838 
839 
840  return aBuffer.makeStringAndClear();
841 }
842 
844 bool SvXMLUnitConverter::convertHex( sal_uInt32& nVal,
845  const OUString& rValue )
846 {
847  if( rValue.getLength() != 8 )
848  return false;
849 
850  nVal = 0;
851  for ( int i = 0; i < 8; i++ )
852  {
853  nVal = ( nVal << 4 )
854  | sal::static_int_cast< sal_uInt32 >( lcl_gethex( rValue[i] ) );
855  }
856 
857  return true;
858 }
859 
861 void SvXMLUnitConverter::convertHex( OUStringBuffer& rBuffer,
862  sal_uInt32 nVal )
863 {
864  for ( int i = 0; i < 8; i++ )
865  {
866  rBuffer.append( sal_Unicode( aHexTab[ nVal >> 28 ] ) );
867  nVal <<= 4;
868  }
869 }
870 
871 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static const sal_Int64 hourPerDay
bool IsXMLToken(const OUString &rString, enum XMLTokenEnum eToken)
compare eToken to the string
Definition: xmltoken.cxx:3434
FieldUnit
void convertDouble(OUStringBuffer &rBuffer, double fNumber) const
convert double number to string (using ::rtl::math) and DO convert to export MapUnit using meCoreMeas...
Definition: xmluconv.cxx:286
sal_Int16 GetXMLMeasureUnit() const
gets the default unit for textual measures
Definition: xmluconv.cxx:115
const char aHexTab[]
Definition: xmluconv.cxx:282
#define XML_NULLDATE
Definition: xmluconv.cxx:63
static bool convertMeasure(sal_Int32 &rValue, const OUString &rString, sal_Int16 nTargetUnit=css::util::MeasureUnit::MM_100TH, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32)
bool convertNumFormat(sal_Int16 &rType, const OUString &rNumFormat, const OUString &rNumLetterSync, bool bNumberNone=false) const
convert num-format and num-letter-sync values to NumberingType
Definition: xmluconv.cxx:574
sal_Int32 mnNextTokenPos
Definition: xmluconv.hxx:58
signed char sal_Int8
static int lcl_gethex(int nChar)
Definition: xmluconv.cxx:270
sal_Unicode mcSeparator
Definition: xmluconv.hxx:59
static const sal_Int64 minutePerDay
void SetXMLMeasureUnit(sal_Int16 const eXMLMeasureUnit)
sets the default unit for textual measures
Definition: xmluconv.cxx:110
bool getNextToken(OUString &rToken)
Definition: xmluconv.cxx:449
const OUString & maTokenString
Definition: xmluconv.hxx:57
uno::Reference< text::XNumberingTypeInfo > m_xNumTypeInfo
Definition: xmluconv.cxx:70
sal_Int16 m_eCoreMeasureUnit
Definition: xmluconv.cxx:67
static void convertDouble(OUStringBuffer &rBuffer, double fNumber, bool bWriteUnits, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
css::uno::Any const & rValue
Definition: ImageStyle.hxx:38
bool convertMeasureToCore(sal_Int32 &rValue, const OUString &rString, sal_Int32 nMin=SAL_MIN_INT32, sal_Int32 nMax=SAL_MAX_INT32) const
convert string to measure with meCoreMeasureUnit, using optional min and max values ...
Definition: xmluconv.cxx:171
sal_uInt16 sal_Unicode
void SetCoreMeasureUnit(sal_Int16 const eCoreMeasureUnit)
sets the default unit for numerical measures
Definition: xmluconv.cxx:105
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
int nCount
XMLTokenEnum
The enumeration of all XML tokens.
Definition: xmltoken.hxx:49
static bool parseDateTime(css::util::DateTime &rDateTime, const OUString &rString)
SvXMLTokenEnumerator(const OUString &rString, sal_Unicode cSeparator=u' ')
Definition: xmluconv.cxx:444
Map a const char* (with length) to a sal_uInt16 value.
Definition: xmlement.hxx:70
int i
uno::Reference< uno::XComponentContext > m_xContext
Definition: xmluconv.cxx:72
const char * GetName() const
Definition: xmlement.hxx:79
void convertDateTime(OUStringBuffer &rBuffer, const double &fDateTime, bool const bAddTimeIf0AM=false)
convert double to ISO Date Time String
Definition: xmluconv.cxx:317
sal_Int16 m_eXMLMeasureUnit
Definition: xmluconv.cxx:68
bool setNullDate(const css::uno::Reference< css::frame::XModel > &xModel)
get the Null Date of the XModel and set it to the UnitConverter
Definition: xmluconv.cxx:305
static bool convertEnumImpl(sal_uInt16 &rEnum, const OUString &rValue, const SvXMLEnumMapEntry< sal_uInt16 > *pMap)
convert string to enum using given token map, if the enum is not found in the map, this method will return false
Definition: xmluconv.cxx:221
const uno::Reference< uno::XComponentContext > m_xContext
static bool lcl_getPositions(const OUString &_sValue, OUString &_rContentX, OUString &_rContentY, OUString &_rContentZ)
Definition: xmluconv.cxx:475
static bool convertB3DVector(::basegfx::B3DVector &rVector, const OUString &rValue)
convert string to basegfx::B3DVector
Definition: xmluconv.cxx:507
static void convertNumLetterSync(OUStringBuffer &rBuffer, sal_Int16 nType)
Definition: xmluconv.cxx:671
std::unique_ptr< char[]> aBuffer
static sal_Int16 GetMeasureUnit(FieldUnit const nFieldUnit)
Definition: xmluconv.cxx:137
static void GetClock(double fTimeInDays, sal_uInt16 &nHour, sal_uInt16 &nMinute, sal_uInt16 &nSecond, double &fFractionOfSecond, int nFractionDecimals)
static sal_Int16 GetUnitFromString(const OUString &rString, sal_Int16 nDefaultUnit)
#define SAL_WARN_IF(condition, area, stream)
const OUString & GetXMLToken(enum XMLTokenEnum eToken)
return the OUString representation for eToken
Definition: xmltoken.cxx:3378
Impl(uno::Reference< uno::XComponentContext > const &xContext, sal_Int16 const eCoreMeasureUnit, sal_Int16 const eXMLMeasureUnit)
Definition: xmluconv.cxx:74
const sal_Int8 XML_MAXDIGITSCOUNT_TIME
Definition: xmluconv.cxx:62
static bool convertHex(sal_uInt32 &nVal, const OUString &rValue)
convert string (hex) to number (sal_uInt32)
Definition: xmluconv.cxx:844
Handling of tokens in XML:
uno::Reference< i18n::XCharacterClassification > m_xCharClass
Definition: xmluconv.cxx:71
QPRO_FUNC_TYPE nType
EnumT GetValue() const
Definition: xmlement.hxx:81
static void convertPropertySet(css::uno::Sequence< css::beans::PropertyValue > &rProps, const css::uno::Reference< css::beans::XPropertySet > &aProperties)
bool convertPosition3D(css::drawing::Position3D &rPosition, const OUString &rValue)
convert string to Position3D
OUString encodeStyleName(const OUString &rName, bool *pEncoded=nullptr) const
Definition: xmluconv.cxx:739
sal_Int32 GetNameLength() const
Definition: xmlement.hxx:80
static const sal_Int64 nanoSecPerDay
const css::uno::Reference< css::text::XNumberingTypeInfo > & getNumTypeInfo() const
gets XNumberingTypeInfo
Definition: xmluconv.cxx:96
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
SvXMLUnitConverter(const SvXMLUnitConverter &)=delete
void convertMeasureToXML(OUStringBuffer &rBuffer, sal_Int32 nMeasure) const
convert measure to string: from meCoreMeasureUnit to meXMLMeasureUnit
Definition: xmluconv.cxx:181
sal_uInt16 nPos
void createNumTypeInfo() const
Definition: xmluconv.cxx:89
::std::unique_ptr< Impl > m_pImpl
Definition: xmluconv.hxx:84
static const sal_Int64 secondPerDay