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