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