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