1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26 #include <com/sun/star/util/DateTime.hpp>
27 #include <com/sun/star/util/Date.hpp>
28 #include <com/sun/star/util/Time.hpp>
29 #include <tools/debug.hxx>
30 #include <rtl/ustrbuf.hxx>
31 #include "xmlehelp.hxx"
32 #include <xmloff/xmlement.hxx>
33 #include <xmloff/xmluconv.hxx>
34 #include <xmloff/xmltoken.hxx>
35 #include <rtl/math.hxx>
36 #include <rtl/logfile.hxx>
37
38 #ifndef _TOOLS_DATE_HXX
39 #include <tools/date.hxx>
40
41 #include <tools/string.hxx>
42
43 #endif
44
45 #include <tools/time.hxx>
46 #include <tools/fldunit.hxx>
47
48 // #110680#
49 //#ifndef _COMPHELPER_PROCESSFACTORY_HXX_
50 //#include <comphelper/processfactory.hxx>
51 //#endif
52 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
53 #include <com/sun/star/style/NumberingType.hpp>
54 #include <com/sun/star/text/XNumberingTypeInfo.hpp>
55 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
56 #include <com/sun/star/i18n/XCharacterClassification.hpp>
57 #include <com/sun/star/i18n/UnicodeType.hpp>
58 #include <basegfx/vector/b3dvector.hxx>
59
60 using namespace rtl;
61 using namespace com::sun::star;
62 using namespace com::sun::star::uno;
63 using namespace com::sun::star::lang;
64 using namespace com::sun::star::text;
65 using namespace com::sun::star::style;
66 using namespace ::com::sun::star::i18n;
67 using namespace ::xmloff::token;
68
69 const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
70 const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6;
71 #define XML_NULLDATE "NullDate"
72
73 OUString SvXMLUnitConverter::msXML_true;
74 OUString SvXMLUnitConverter::msXML_false;
75
initXMLStrings()76 void SvXMLUnitConverter::initXMLStrings()
77 {
78 if( msXML_true.getLength() == 0 )
79 {
80 msXML_true = GetXMLToken(XML_TRUE);
81 msXML_false = GetXMLToken(XML_FALSE);
82 }
83 }
84
createNumTypeInfo() const85 void SvXMLUnitConverter::createNumTypeInfo() const
86 {
87 // #110680#
88 //Reference< lang::XMultiServiceFactory > xServiceFactory =
89 // comphelper::getProcessServiceFactory();
90 //OSL_ENSURE( xServiceFactory.is(),
91 // "XMLUnitConverter: got no service factory" );
92
93 if( mxServiceFactory.is() )
94 {
95 ((SvXMLUnitConverter *)this)->xNumTypeInfo =
96 Reference < XNumberingTypeInfo > (
97 mxServiceFactory->createInstance(
98 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.DefaultNumberingProvider") ) ), UNO_QUERY );
99 }
100 }
101
102 /** constructs a SvXMLUnitConverter. The core measure unit is the
103 default unit for numerical measures, the XML measure unit is
104 the default unit for textual measures
105 */
106
107 // #110680#
108 //SvXMLUnitConverter::SvXMLUnitConverter( MapUnit eCoreMeasureUnit,
109 // MapUnit eXMLMeasureUnit ) :
SvXMLUnitConverter(MapUnit eCoreMeasureUnit,MapUnit eXMLMeasureUnit,const uno::Reference<lang::XMultiServiceFactory> & xServiceFactory)110 SvXMLUnitConverter::SvXMLUnitConverter(
111 MapUnit eCoreMeasureUnit,
112 MapUnit eXMLMeasureUnit,
113 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) :
114 aNullDate(30, 12, 1899),
115 mxServiceFactory( xServiceFactory )
116 {
117 DBG_ASSERT( mxServiceFactory.is(), "got no service manager" );
118
119 meCoreMeasureUnit = eCoreMeasureUnit;
120 meXMLMeasureUnit = eXMLMeasureUnit;
121 }
122
~SvXMLUnitConverter()123 SvXMLUnitConverter::~SvXMLUnitConverter()
124 {
125 }
126
GetMapUnit(sal_Int16 nFieldUnit)127 MapUnit SvXMLUnitConverter::GetMapUnit(sal_Int16 nFieldUnit)
128 {
129 MapUnit eUnit = MAP_INCH;
130 switch( nFieldUnit )
131 {
132 case FUNIT_MM:
133 eUnit = MAP_MM;
134 break;
135 case FUNIT_CM:
136 case FUNIT_M:
137 case FUNIT_KM:
138 eUnit = MAP_CM;
139 break;
140 case FUNIT_TWIP:
141 eUnit = MAP_TWIP;
142 break;
143 case FUNIT_POINT:
144 case FUNIT_PICA:
145 eUnit = MAP_POINT;
146 break;
147 // case FUNIT_INCH:
148 // case FUNIT_FOOT:
149 // case FUNIT_MILE:
150 // eUnit = MAP_INCH;
151 // break;
152 case FUNIT_100TH_MM:
153 eUnit = MAP_100TH_MM;
154 break;
155 }
156 return eUnit;
157 }
158
159 /** convert string to measure using optional min and max values*/
convertMeasure(sal_Int32 & nValue,const OUString & rString,sal_Int32 nMin,sal_Int32 nMax) const160 sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& nValue,
161 const OUString& rString,
162 sal_Int32 nMin, sal_Int32 nMax ) const
163 {
164 return SvXMLUnitConverter::convertMeasure( nValue, rString,
165 meCoreMeasureUnit,
166 nMin, nMax );
167 }
168
169 /** convert measure to string */
convertMeasure(OUStringBuffer & rString,sal_Int32 nMeasure) const170 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString,
171 sal_Int32 nMeasure ) const
172 {
173 SvXMLUnitConverter::convertMeasure( rString, nMeasure,
174 meCoreMeasureUnit,
175 meXMLMeasureUnit );
176 }
177
178 /** convert measure with given unit to string */
convertMeasure(OUStringBuffer & rString,sal_Int32 nMeasure,MapUnit eSrcUnit) const179 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString,
180 sal_Int32 nMeasure,
181 MapUnit eSrcUnit ) const
182 {
183 SvXMLUnitConverter::convertMeasure( rString, nMeasure,
184 eSrcUnit,
185 meXMLMeasureUnit );
186 }
187
188 /** convert the value from the given string to an int value
189 with the given map unit using optional min and max values
190 */
convertMeasure(sal_Int32 & rValue,const OUString & rString,MapUnit eDstUnit,sal_Int32 nMin,sal_Int32 nMax)191 sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& rValue,
192 const OUString& rString,
193 MapUnit eDstUnit,
194 sal_Int32 nMin, sal_Int32 nMax )
195 {
196 sal_Bool bNeg = sal_False;
197 double nVal = 0;
198
199 sal_Int32 nPos = 0;
200 const sal_Int32 nLen = rString.getLength();
201
202 // skip white space
203 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
204 nPos++;
205
206 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
207 {
208 bNeg = sal_True;
209 ++nPos;
210 }
211
212 // get number
213 while( nPos < nLen &&
214 sal_Unicode('0') <= rString[nPos] &&
215 sal_Unicode('9') >= rString[nPos] )
216 {
217 // TODO: check overflow!
218 nVal *= 10;
219 nVal += (rString[nPos] - sal_Unicode('0'));
220 ++nPos;
221 }
222 double nDiv = 1.;
223 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
224 {
225 ++nPos;
226
227 while( nPos < nLen &&
228 sal_Unicode('0') <= rString[nPos] &&
229 sal_Unicode('9') >= rString[nPos] )
230 {
231 // TODO: check overflow!
232 nDiv *= 10;
233 nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv );
234 ++nPos;
235 }
236 }
237
238 // skip white space
239 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
240 ++nPos;
241
242 if( nPos < nLen )
243 {
244
245 if( MAP_RELATIVE == eDstUnit )
246 {
247 if( sal_Unicode('%') != rString[nPos] )
248 return sal_False;
249 }
250 else if( MAP_PIXEL == eDstUnit )
251 {
252 if( nPos + 1 >= nLen ||
253 (sal_Unicode('p') != rString[nPos] &&
254 sal_Unicode('P') != rString[nPos])||
255 (sal_Unicode('x') != rString[nPos+1] &&
256 sal_Unicode('X') != rString[nPos+1]) )
257 return sal_False;
258 }
259 else
260 {
261 DBG_ASSERT( MAP_TWIP == eDstUnit || MAP_POINT == eDstUnit ||
262 MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit, "unit is not supported");
263 const sal_Char *aCmpsL[2] = { 0, 0 };
264 const sal_Char *aCmpsU[2] = { 0, 0 };
265 double aScales[2] = { 1., 1. };
266
267 if( MAP_TWIP == eDstUnit )
268 {
269 switch( rString[nPos] )
270 {
271 case sal_Unicode('c'):
272 case sal_Unicode('C'):
273 aCmpsL[0] = "cm";
274 aCmpsU[0] = "CM";
275 aScales[0] = (72.*20.)/2.54; // twip
276 break;
277 case sal_Unicode('e'):
278 case sal_Unicode('E'):
279 // pCmp1 = sXML_unit_em;
280 // nToken1 = CSS1_EMS;
281
282 // pCmp2 = sXML_unit_ex;
283 // nToken2 = CSS1_EMX;
284 break;
285 case sal_Unicode('i'):
286 case sal_Unicode('I'):
287 aCmpsL[0] = "in";
288 aCmpsU[0] = "IN";
289 aScales[0] = 72.*20.; // twip
290 break;
291 case sal_Unicode('m'):
292 case sal_Unicode('M'):
293 aCmpsL[0] = "mm";
294 aCmpsU[0] = "MM";
295 aScales[0] = (72.*20.)/25.4; // twip
296 break;
297 case sal_Unicode('p'):
298 case sal_Unicode('P'):
299 aCmpsL[0] = "pt";
300 aCmpsU[0] = "PT";
301 aScales[0] = 20.; // twip
302
303 aCmpsL[1] = "pc";
304 aCmpsU[1] = "PC";
305 aScales[1] = 12.*20.; // twip
306
307 // pCmp3 = sXML_unit_px;
308 // nToken3 = CSS1_PIXLENGTH;
309 break;
310 }
311 }
312 else if( MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit )
313 {
314 double nScaleFactor = (MAP_100TH_MM == eDstUnit) ? 100.0 : 10.0;
315 switch( rString[nPos] )
316 {
317 case sal_Unicode('c'):
318 case sal_Unicode('C'):
319 aCmpsL[0] = "cm";
320 aCmpsU[0] = "CM";
321 aScales[0] = 10.0 * nScaleFactor; // mm/100
322 break;
323 case sal_Unicode('e'):
324 case sal_Unicode('E'):
325 // pCmp1 = sXML_unit_em;
326 // nToken1 = CSS1_EMS;
327
328 // pCmp2 = sXML_unit_ex;
329 // nToken2 = CSS1_EMX;
330 break;
331 case sal_Unicode('i'):
332 case sal_Unicode('I'):
333 aCmpsL[0] = "in";
334 aCmpsU[0] = "IN";
335 aScales[0] = 1000.*2.54; // mm/100
336 break;
337 case sal_Unicode('m'):
338 case sal_Unicode('M'):
339 aCmpsL[0] = "mm";
340 aCmpsU[0] = "MM";
341 aScales[0] = 1.0 * nScaleFactor; // mm/100
342 break;
343 case sal_Unicode('p'):
344 case sal_Unicode('P'):
345 aCmpsL[0] = "pt";
346 aCmpsU[0] = "PT";
347 aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
348
349 aCmpsL[1] = "pc";
350 aCmpsU[1] = "PC";
351 aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
352
353 // pCmp3 = sXML_unit_px;
354 // nToken3 = CSS1_PIXLENGTH;
355 break;
356 }
357 }
358 else if( MAP_POINT == eDstUnit )
359 {
360 if( rString[nPos] == 'p' || rString[nPos] == 'P' )
361 {
362 aCmpsL[0] = "pt";
363 aCmpsU[0] = "PT";
364 aScales[0] = 1;
365 }
366 }
367
368 if( aCmpsL[0] == NULL )
369 return sal_False;
370
371 double nScale = 0.;
372 for( sal_uInt16 i= 0; i < 2; ++i )
373 {
374 const sal_Char *pL = aCmpsL[i];
375 if( pL )
376 {
377 const sal_Char *pU = aCmpsU[i];
378 while( nPos < nLen && *pL )
379 {
380 sal_Unicode c = rString[nPos];
381 if( c != *pL && c != *pU )
382 break;
383 ++pL;
384 ++pU;
385 ++nPos;
386 }
387 if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
388 {
389 nScale = aScales[i];
390 break;
391 }
392 }
393 }
394
395 if( 0. == nScale )
396 return sal_False;
397
398 // TODO: check overflow
399 if( nScale != 1. )
400 nVal *= nScale;
401 }
402 }
403
404 nVal += .5;
405 if( bNeg )
406 nVal = -nVal;
407
408 if( nVal <= (double)nMin )
409 rValue = nMin;
410 else if( nVal >= (double)nMax )
411 rValue = nMax;
412 else
413 rValue = (sal_Int32)nVal;
414
415 return sal_True;
416 }
417
418 /** convert measure in given unit to string with given unit */
convertMeasure(OUStringBuffer & rBuffer,sal_Int32 nMeasure,MapUnit eSrcUnit,MapUnit eDstUnit)419 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rBuffer,
420 sal_Int32 nMeasure,
421 MapUnit eSrcUnit,
422 MapUnit eDstUnit )
423 {
424 if( eSrcUnit == MAP_RELATIVE )
425 {
426 DBG_ASSERT( eDstUnit == MAP_RELATIVE,
427 "MAP_RELATIVE only maps to MAP_RELATIVE!" );
428
429 rBuffer.append( nMeasure );
430 rBuffer.append( sal_Unicode('%' ) );
431 }
432 else
433 {
434 SvXMLExportHelper::AddLength( nMeasure, eSrcUnit,
435 rBuffer, eDstUnit );
436 }
437 }
438
439 /** convert string to boolean */
convertBool(sal_Bool & rBool,const OUString & rString)440 sal_Bool SvXMLUnitConverter::convertBool( sal_Bool& rBool,
441 const OUString& rString )
442 {
443 rBool = IsXMLToken(rString, XML_TRUE);
444
445 return rBool || IsXMLToken(rString, XML_FALSE);
446 }
447
448 /** convert boolean to string */
convertBool(OUStringBuffer & rBuffer,sal_Bool bValue)449 void SvXMLUnitConverter::convertBool( OUStringBuffer& rBuffer,
450 sal_Bool bValue )
451 {
452 rBuffer.append( GetXMLToken( bValue ? XML_TRUE : XML_FALSE ) );
453 }
454
455 /** convert string to percent */
convertPercent(sal_Int32 & rPercent,const OUString & rString)456 sal_Bool SvXMLUnitConverter::convertPercent( sal_Int32& rPercent,
457 const OUString& rString )
458 {
459 return convertMeasure( rPercent, rString, MAP_RELATIVE );
460 }
461
462 /** convert percent to string */
convertPercent(OUStringBuffer & rBuffer,sal_Int32 nValue)463 void SvXMLUnitConverter::convertPercent( OUStringBuffer& rBuffer,
464 sal_Int32 nValue )
465 {
466 rBuffer.append( nValue );
467 rBuffer.append( sal_Unicode('%' ) );
468 }
469
470 /** convert string to pixel measure */
convertMeasurePx(sal_Int32 & rPixel,const OUString & rString)471 sal_Bool SvXMLUnitConverter::convertMeasurePx( sal_Int32& rPixel,
472 const OUString& rString )
473 {
474 return convertMeasure( rPixel, rString, MAP_PIXEL );
475 }
476
477 /** convert pixel measure to string */
convertMeasurePx(OUStringBuffer & rBuffer,sal_Int32 nValue)478 void SvXMLUnitConverter::convertMeasurePx( OUStringBuffer& rBuffer,
479 sal_Int32 nValue )
480 {
481 rBuffer.append( nValue );
482 rBuffer.append( sal_Unicode('p' ) );
483 rBuffer.append( sal_Unicode('x' ) );
484 }
485
486 /** convert string to enum using given enum map, if the enum is
487 not found in the map, this method will return false
488 */
convertEnum(sal_uInt16 & rEnum,const OUString & rValue,const SvXMLEnumStringMapEntry * pMap)489 sal_Bool SvXMLUnitConverter::convertEnum( sal_uInt16& rEnum,
490 const OUString& rValue,
491 const SvXMLEnumStringMapEntry *pMap )
492 {
493 while( pMap->pName )
494 {
495 if( rValue.equalsAsciiL( pMap->pName, pMap->nNameLength ) )
496 {
497 rEnum = pMap->nValue;
498 return sal_True;
499 }
500 ++pMap;
501 }
502
503 return sal_False;
504 }
505
506 /** convert string to enum using given token map, if the enum is
507 not found in the map, this method will return false */
convertEnum(sal_uInt16 & rEnum,const OUString & rValue,const SvXMLEnumMapEntry * pMap)508 sal_Bool SvXMLUnitConverter::convertEnum(
509 sal_uInt16& rEnum,
510 const OUString& rValue,
511 const SvXMLEnumMapEntry *pMap )
512 {
513 while( pMap->eToken != XML_TOKEN_INVALID )
514 {
515 if( IsXMLToken( rValue, pMap->eToken ) )
516 {
517 rEnum = pMap->nValue;
518 return sal_True;
519 }
520 ++pMap;
521 }
522 return sal_False;
523 }
524
525 /** convert enum to string using given enum map with optional
526 default string. If the enum is not found in the map,
527 this method will either use the given default or return
528 false if not default is set
529 */
convertEnum(OUStringBuffer & rBuffer,sal_uInt16 nValue,const SvXMLEnumStringMapEntry * pMap,sal_Char * pDefault)530 sal_Bool SvXMLUnitConverter::convertEnum( OUStringBuffer& rBuffer,
531 sal_uInt16 nValue,
532 const SvXMLEnumStringMapEntry *pMap,
533 sal_Char * pDefault /* = NULL */ )
534 {
535 const sal_Char *pStr = pDefault;
536
537 while( pMap->pName )
538 {
539 if( pMap->nValue == nValue )
540 {
541 pStr = pMap->pName;
542 break;
543 }
544 ++pMap;
545 }
546
547 if( NULL == pStr )
548 pStr = pDefault;
549
550 if( NULL != pStr )
551 rBuffer.appendAscii( pStr );
552
553 return NULL != pStr;
554 }
555
556 /** convert enum to string using given token map with an optional
557 default token. If the enum is not found in the map,
558 this method will either use the given default or return
559 false if no default is set */
convertEnum(OUStringBuffer & rBuffer,unsigned int nValue,const SvXMLEnumMapEntry * pMap,enum XMLTokenEnum eDefault)560 sal_Bool SvXMLUnitConverter::convertEnum(
561 OUStringBuffer& rBuffer,
562 unsigned int nValue,
563 const SvXMLEnumMapEntry *pMap,
564 enum XMLTokenEnum eDefault)
565 {
566 enum XMLTokenEnum eTok = eDefault;
567
568 while( pMap->eToken != XML_TOKEN_INVALID )
569 {
570 if( pMap->nValue == nValue )
571 {
572 eTok = pMap->eToken;
573 break;
574 }
575 ++pMap;
576 }
577
578 // the map may have contained XML_TOKEN_INVALID
579 if( eTok == XML_TOKEN_INVALID )
580 eTok = eDefault;
581
582 if( eTok != XML_TOKEN_INVALID )
583 rBuffer.append( GetXMLToken(eTok) );
584
585 return (eTok != XML_TOKEN_INVALID);
586 }
587
lcl_gethex(int nChar)588 int lcl_gethex( int nChar )
589 {
590 if( nChar >= '0' && nChar <= '9' )
591 return nChar - '0';
592 else if( nChar >= 'a' && nChar <= 'f' )
593 return nChar - 'a' + 10;
594 else if( nChar >= 'A' && nChar <= 'F' )
595 return nChar - 'A' + 10;
596 else
597 return 0;
598 }
599
600 /** convert string to color */
convertColor(Color & rColor,const OUString & rValue)601 sal_Bool SvXMLUnitConverter::convertColor( Color& rColor,
602 const OUString& rValue )
603 {
604 if( rValue.getLength() != 7 || rValue[0] != '#' )
605 return sal_False;
606
607 rColor.SetRed(
608 sal::static_int_cast< sal_uInt8 >(
609 lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] ) ) );
610
611 rColor.SetGreen(
612 sal::static_int_cast< sal_uInt8 >(
613 lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) ) );
614
615 rColor.SetBlue(
616 sal::static_int_cast< sal_uInt8 >(
617 lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) ) );
618
619 return sal_True;
620 }
621
622 static sal_Char aHexTab[] = "0123456789abcdef";
623
624 /** convert color to string */
convertColor(OUStringBuffer & rBuffer,const Color & rCol)625 void SvXMLUnitConverter::convertColor( OUStringBuffer& rBuffer,
626 const Color& rCol )
627 {
628 rBuffer.append( sal_Unicode( '#' ) );
629
630 sal_uInt8 nCol = rCol.GetRed();
631 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
632 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
633
634 nCol = rCol.GetGreen();
635 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
636 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
637
638 nCol = rCol.GetBlue();
639 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
640 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
641 }
642
643 /** convert number to string */
convertNumber(OUStringBuffer & rBuffer,sal_Int32 nNumber)644 void SvXMLUnitConverter::convertNumber( OUStringBuffer& rBuffer,
645 sal_Int32 nNumber )
646 {
647 rBuffer.append( sal_Int32( nNumber ) );
648 }
649
650 /** convert string to number with optional min and max values */
convertNumber(sal_Int32 & rValue,const OUString & rString,sal_Int32 nMin,sal_Int32 nMax)651 sal_Bool SvXMLUnitConverter::convertNumber( sal_Int32& rValue,
652 const OUString& rString,
653 sal_Int32 nMin, sal_Int32 nMax )
654 {
655 rValue = 0;
656 sal_Int64 nNumber = 0;
657 sal_Bool bRet = convertNumber64(nNumber,rString,nMin,nMax);
658 if ( bRet )
659 rValue = static_cast<sal_Int32>(nNumber);
660 return bRet;
661 }
662
663 /** convert 64-bit number to string */
convertNumber64(OUStringBuffer & rBuffer,sal_Int64 nNumber)664 void SvXMLUnitConverter::convertNumber64( OUStringBuffer& rBuffer,
665 sal_Int64 nNumber )
666 {
667 rBuffer.append( nNumber );
668 }
669
670 /** convert string to 64-bit number with optional min and max values */
convertNumber64(sal_Int64 & rValue,const OUString & rString,sal_Int64 nMin,sal_Int64 nMax)671 sal_Bool SvXMLUnitConverter::convertNumber64( sal_Int64& rValue,
672 const OUString& rString,
673 sal_Int64 nMin, sal_Int64 nMax )
674 {
675 sal_Bool bNeg = sal_False;
676 rValue = 0;
677
678 sal_Int32 nPos = 0;
679 const sal_Int32 nLen = rString.getLength();
680
681 // skip white space
682 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
683 ++nPos;
684
685 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
686 {
687 bNeg = sal_True;
688 ++nPos;
689 }
690
691 // get number
692 while( nPos < nLen &&
693 sal_Unicode('0') <= rString[nPos] &&
694 sal_Unicode('9') >= rString[nPos] )
695 {
696 // TODO: check overflow!
697 rValue *= 10;
698 rValue += (rString[nPos] - sal_Unicode('0'));
699 ++nPos;
700 }
701
702 if( bNeg )
703 rValue *= -1;
704
705 return ( nPos == nLen && rValue >= nMin && rValue <= nMax );
706 }
707
708 /** convert double number to string (using ::rtl::math) */
convertDouble(::rtl::OUStringBuffer & rBuffer,double fNumber,sal_Bool bWriteUnits) const709 void SvXMLUnitConverter::convertDouble(::rtl::OUStringBuffer& rBuffer,
710 double fNumber, sal_Bool bWriteUnits) const
711 {
712 SvXMLUnitConverter::convertDouble(rBuffer, fNumber,
713 bWriteUnits, meCoreMeasureUnit, meXMLMeasureUnit);
714 }
715
716 /** convert double number to string (using ::rtl::math) */
convertDouble(::rtl::OUStringBuffer & rBuffer,double fNumber,sal_Bool bWriteUnits,MapUnit eCoreUnit,MapUnit eDstUnit)717 void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer,
718 double fNumber, sal_Bool bWriteUnits, MapUnit eCoreUnit, MapUnit eDstUnit)
719 {
720 if(MAP_RELATIVE == eCoreUnit)
721 {
722 DBG_ASSERT(eDstUnit == MAP_RELATIVE, "MAP_RELATIVE only maps to MAP_RELATIVE!" );
723 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True);
724 if(bWriteUnits)
725 rBuffer.append(sal_Unicode('%'));
726 }
727 else
728 {
729 OUStringBuffer sUnit;
730 double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eDstUnit);
731 if(fFactor != 1.0)
732 fNumber *= fFactor;
733 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True);
734 if(bWriteUnits)
735 rBuffer.append(sUnit);
736 }
737 }
738
739 /** convert double number to string (using ::rtl::math) */
convertDouble(::rtl::OUStringBuffer & rBuffer,double fNumber)740 void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber)
741 {
742 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True);
743 }
744
745 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString,sal_Bool bLookForUnits) const746 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue,
747 const ::rtl::OUString& rString, sal_Bool bLookForUnits) const
748 {
749 if(bLookForUnits)
750 {
751 MapUnit eSrcUnit = SvXMLExportHelper::GetUnitFromString(rString, meCoreMeasureUnit);
752
753 return SvXMLUnitConverter::convertDouble(rValue, rString,
754 eSrcUnit, meCoreMeasureUnit);
755 }
756 else
757 {
758 return SvXMLUnitConverter::convertDouble(rValue, rString);
759 }
760 }
761
762 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString,MapUnit eSrcUnit,MapUnit eCoreUnit)763 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue,
764 const ::rtl::OUString& rString, MapUnit eSrcUnit, MapUnit eCoreUnit)
765 {
766 rtl_math_ConversionStatus eStatus;
767 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
768
769 if(eStatus == rtl_math_ConversionStatus_Ok)
770 {
771 OUStringBuffer sUnit;
772 const double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eSrcUnit);
773 if(fFactor != 1.0 && fFactor != 0.0)
774 rValue /= fFactor;
775 }
776
777 return ( eStatus == rtl_math_ConversionStatus_Ok );
778 }
779
780 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString)781 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, const ::rtl::OUString& rString)
782 {
783 rtl_math_ConversionStatus eStatus;
784 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
785 return ( eStatus == rtl_math_ConversionStatus_Ok );
786 }
787
788 /** get the Null Date of the XModel and set it to the UnitConverter */
setNullDate(const com::sun::star::uno::Reference<com::sun::star::frame::XModel> & xModel)789 sal_Bool SvXMLUnitConverter::setNullDate(const com::sun::star::uno::Reference <com::sun::star::frame::XModel>& xModel)
790 {
791 com::sun::star::uno::Reference <com::sun::star::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, com::sun::star::uno::UNO_QUERY);
792 if (xNumberFormatsSupplier.is())
793 {
794 const com::sun::star::uno::Reference <com::sun::star::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings();
795 return xPropertySet.is() && (xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(XML_NULLDATE))) >>= aNullDate);
796 }
797 return sal_False;
798 }
799
800 /** convert double to ISO Time String; negative durations allowed */
convertTime(::rtl::OUStringBuffer & rBuffer,const double & fTime)801 void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer,
802 const double& fTime)
803 {
804
805 double fValue = fTime;
806
807 // take care of negative durations as specified in:
808 // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
809 if (fValue < 0.0)
810 {
811 rBuffer.append(sal_Unicode('-'));
812 fValue = - fValue;
813 }
814
815 rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
816 fValue *= 24;
817 double fHoursValue = ::rtl::math::approxFloor (fValue);
818 fValue -= fHoursValue;
819 fValue *= 60;
820 double fMinsValue = ::rtl::math::approxFloor (fValue);
821 fValue -= fMinsValue;
822 fValue *= 60;
823 double fSecsValue = ::rtl::math::approxFloor (fValue);
824 fValue -= fSecsValue;
825 double f100SecsValue;
826 if (fValue > 0.00001)
827 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
828 else
829 f100SecsValue = 0.0;
830
831 if (f100SecsValue == 1.0)
832 {
833 f100SecsValue = 0.0;
834 fSecsValue += 1.0;
835 }
836 if (fSecsValue >= 60.0)
837 {
838 fSecsValue -= 60.0;
839 fMinsValue += 1.0;
840 }
841 if (fMinsValue >= 60.0)
842 {
843 fMinsValue -= 60.0;
844 fHoursValue += 1.0;
845 }
846
847 if (fHoursValue < 10)
848 rBuffer.append( sal_Unicode('0'));
849 rBuffer.append( sal_Int32( fHoursValue));
850 rBuffer.append( sal_Unicode('H'));
851 if (fMinsValue < 10)
852 rBuffer.append( sal_Unicode('0'));
853 rBuffer.append( sal_Int32( fMinsValue));
854 rBuffer.append( sal_Unicode('M'));
855 if (fSecsValue < 10)
856 rBuffer.append( sal_Unicode('0'));
857 rBuffer.append( sal_Int32( fSecsValue));
858 if (f100SecsValue > 0.0)
859 {
860 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
861 rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
862 sal_True));
863 if ( a100th.getLength() > 2 )
864 {
865 rBuffer.append( sal_Unicode('.'));
866 rBuffer.append( a100th.copy( 2 ) ); // strip 0.
867 }
868 }
869 rBuffer.append( sal_Unicode('S'));
870 }
871
872 /** convert ISO Time String to double; negative durations allowed */
lcl_convertTime(const::rtl::OUString & rString,sal_Int32 & o_rDays,sal_Int32 & o_rHours,sal_Int32 & o_rMins,sal_Int32 & o_rSecs,sal_Bool & o_rIsNegativeTime,double & o_rFractionalSecs)873 static bool lcl_convertTime( const ::rtl::OUString& rString, sal_Int32& o_rDays, sal_Int32& o_rHours, sal_Int32& o_rMins,
874 sal_Int32& o_rSecs, sal_Bool& o_rIsNegativeTime, double& o_rFractionalSecs )
875 {
876 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
877 const sal_Unicode* pStr = aTrimmed.getStr();
878
879 // negative time duration?
880 if ( sal_Unicode('-') == (*pStr) )
881 {
882 o_rIsNegativeTime = sal_True;
883 pStr++;
884 }
885
886 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
887 return false;
888
889 ::rtl::OUString sDoubleStr;
890 sal_Bool bSuccess = true;
891 sal_Bool bDone = sal_False;
892 sal_Bool bTimePart = sal_False;
893 sal_Bool bIsFraction = sal_False;
894 sal_Int32 nTemp = 0;
895
896 while ( bSuccess && !bDone )
897 {
898 sal_Unicode c = *(pStr++);
899 if ( !c ) // end
900 bDone = sal_True;
901 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
902 {
903 if ( nTemp >= SAL_MAX_INT32 / 10 )
904 bSuccess = false;
905 else
906 {
907 if ( !bIsFraction )
908 {
909 nTemp *= 10;
910 nTemp += (c - sal_Unicode('0'));
911 }
912 else
913 {
914 sDoubleStr += OUString::valueOf(c);
915 }
916 }
917 }
918 else if ( bTimePart )
919 {
920 if ( c == sal_Unicode('H') )
921 {
922 o_rHours = nTemp;
923 nTemp = 0;
924 }
925 else if ( c == sal_Unicode('M') )
926 {
927 o_rMins = nTemp;
928 nTemp = 0;
929 }
930 else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
931 {
932 o_rSecs = nTemp;
933 nTemp = 0;
934 bIsFraction = sal_True;
935 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
936 }
937 else if ( c == sal_Unicode('S') )
938 {
939 if ( !bIsFraction )
940 {
941 o_rSecs = nTemp;
942 nTemp = 0;
943 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
944 }
945 }
946 else
947 bSuccess = false; // invalid character
948 }
949 else
950 {
951 if ( c == sal_Unicode('T') ) // "T" starts time part
952 bTimePart = sal_True;
953 else if ( c == sal_Unicode('D') )
954 {
955 o_rDays = nTemp;
956 nTemp = 0;
957 }
958 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
959 {
960 //! how many days is a year or month?
961
962 DBG_ERROR("years or months in duration: not implemented");
963 bSuccess = false;
964 }
965 else
966 bSuccess = false; // invalid character
967 }
968 }
969
970 if ( bSuccess )
971 o_rFractionalSecs = sDoubleStr.toDouble();
972 return bSuccess;
973 }
974
convertTime(double & fTime,const::rtl::OUString & rString)975 sal_Bool SvXMLUnitConverter::convertTime( double& fTime,
976 const ::rtl::OUString& rString)
977 {
978 sal_Int32 nDays = 0;
979 sal_Int32 nHours = 0;
980 sal_Int32 nMins = 0;
981 sal_Int32 nSecs = 0;
982 sal_Bool bIsNegativeDuration = sal_False;
983 double fFractionalSecs = 0.0;
984 if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) )
985 {
986 if ( nDays )
987 nHours += nDays * 24; // add the days to the hours part
988 double fTempTime = 0.0;
989 double fHour = nHours;
990 double fMin = nMins;
991 double fSec = nSecs;
992 double fSec100 = 0.0;
993 fTempTime = fHour / 24;
994 fTempTime += fMin / (24 * 60);
995 fTempTime += fSec / (24 * 60 * 60);
996 fTempTime += fSec100 / (24 * 60 * 60 * 60);
997 fTempTime += fFractionalSecs / (24 * 60 * 60);
998
999 // negative duration?
1000 if ( bIsNegativeDuration )
1001 {
1002 fTempTime = -fTempTime;
1003 }
1004
1005 fTime = fTempTime;
1006 return sal_True;
1007 }
1008 return sal_False;
1009 }
1010
1011 /** convert util::DateTime to ISO Time String */
convertTime(::rtl::OUStringBuffer & rBuffer,const::com::sun::star::util::DateTime & rDateTime)1012 void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer,
1013 const ::com::sun::star::util::DateTime& rDateTime )
1014 {
1015 double fHour = rDateTime.Hours;
1016 double fMin = rDateTime.Minutes;
1017 double fSec = rDateTime.Seconds;
1018 double fSec100 = rDateTime.HundredthSeconds;
1019 double fTempTime = fHour / 24;
1020 fTempTime += fMin / (24 * 60);
1021 fTempTime += fSec / (24 * 60 * 60);
1022 fTempTime += fSec100 / (24 * 60 * 60 * 100);
1023 convertTime( rBuffer, fTempTime );
1024 }
1025
1026 /** convert ISO Time String to util::DateTime */
convertTime(::com::sun::star::util::DateTime & rDateTime,const::rtl::OUString & rString)1027 sal_Bool SvXMLUnitConverter::convertTime( ::com::sun::star::util::DateTime& rDateTime,
1028 const ::rtl::OUString& rString )
1029 {
1030 sal_Int32 nDays = 0, nHours = 0, nMins = 0, nSecs = 0;
1031 sal_Bool bIsNegativeDuration = sal_False;
1032 double fFractionalSecs = 0.0;
1033 if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) )
1034 {
1035 rDateTime.Year = 0;
1036 rDateTime.Month = 0;
1037 rDateTime.Day = 0;
1038 rDateTime.Hours = static_cast < sal_uInt16 > ( nHours );
1039 rDateTime.Minutes = static_cast < sal_uInt16 > ( nMins );
1040 rDateTime.Seconds = static_cast < sal_uInt16 > ( nSecs );
1041 rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( fFractionalSecs * 100.0 );
1042
1043 return sal_True;
1044 }
1045 return sal_False;
1046 }
1047
1048 /** convert double to ISO Date Time String */
convertDateTime(::rtl::OUStringBuffer & rBuffer,const double & fDateTime,const com::sun::star::util::Date & aTempNullDate,sal_Bool bAddTimeIf0AM)1049 void SvXMLUnitConverter::convertDateTime( ::rtl::OUStringBuffer& rBuffer,
1050 const double& fDateTime,
1051 const com::sun::star::util::Date& aTempNullDate,
1052 sal_Bool bAddTimeIf0AM )
1053 {
1054 double fValue = fDateTime;
1055 sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue));
1056 Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
1057 aDate += nValue;
1058 fValue -= nValue;
1059 double fCount;
1060 if (nValue > 0)
1061 fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1;
1062 else if (nValue < 0)
1063 fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1;
1064 else
1065 fCount = 0.0;
1066 sal_Int16 nCount = sal_Int16(fCount);
1067 sal_Bool bHasTime(sal_False);
1068 double fHoursValue = 0;
1069 double fMinsValue = 0;
1070 double fSecsValue = 0;
1071 double f100SecsValue = 0;
1072 if (fValue > 0.0)
1073 {
1074 bHasTime = sal_True;
1075 fValue *= 24;
1076 fHoursValue = ::rtl::math::approxFloor (fValue);
1077 fValue -= fHoursValue;
1078 fValue *= 60;
1079 fMinsValue = ::rtl::math::approxFloor (fValue);
1080 fValue -= fMinsValue;
1081 fValue *= 60;
1082 fSecsValue = ::rtl::math::approxFloor (fValue);
1083 fValue -= fSecsValue;
1084 if (fValue > 0.0)
1085 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount);
1086 else
1087 f100SecsValue = 0.0;
1088
1089 if (f100SecsValue == 1.0)
1090 {
1091 f100SecsValue = 0.0;
1092 fSecsValue += 1.0;
1093 }
1094 if (fSecsValue >= 60.0)
1095 {
1096 fSecsValue -= 60.0;
1097 fMinsValue += 1.0;
1098 }
1099 if (fMinsValue >= 60.0)
1100 {
1101 fMinsValue -= 60.0;
1102 fHoursValue += 1.0;
1103 }
1104 if (fHoursValue >= 24.0)
1105 {
1106 fHoursValue -= 24.0;
1107 aDate += 1;
1108 }
1109 }
1110 rBuffer.append( sal_Int32( aDate.GetYear()));
1111 rBuffer.append( sal_Unicode('-'));
1112 sal_uInt16 nTemp = aDate.GetMonth();
1113 if (nTemp < 10)
1114 rBuffer.append( sal_Unicode('0'));
1115 rBuffer.append( sal_Int32( nTemp));
1116 rBuffer.append( sal_Unicode('-'));
1117 nTemp = aDate.GetDay();
1118 if (nTemp < 10)
1119 rBuffer.append( sal_Unicode('0'));
1120 rBuffer.append( sal_Int32( nTemp));
1121 if(bHasTime || bAddTimeIf0AM)
1122 {
1123 rBuffer.append( sal_Unicode('T'));
1124 if (fHoursValue < 10)
1125 rBuffer.append( sal_Unicode('0'));
1126 rBuffer.append( sal_Int32( fHoursValue));
1127 rBuffer.append( sal_Unicode(':'));
1128 if (fMinsValue < 10)
1129 rBuffer.append( sal_Unicode('0'));
1130 rBuffer.append( sal_Int32( fMinsValue));
1131 rBuffer.append( sal_Unicode(':'));
1132 if (fSecsValue < 10)
1133 rBuffer.append( sal_Unicode('0'));
1134 rBuffer.append( sal_Int32( fSecsValue));
1135 if (f100SecsValue > 0.0)
1136 {
1137 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
1138 rtl_math_StringFormat_F,
1139 XML_MAXDIGITSCOUNT_TIME - nCount, '.', sal_True));
1140 if ( a100th.getLength() > 2 )
1141 {
1142 rBuffer.append( sal_Unicode('.'));
1143 rBuffer.append( a100th.copy( 2 ) ); // strip 0.
1144 }
1145 }
1146 }
1147 }
1148
1149 /** convert ISO Date Time String to double */
convertDateTime(double & fDateTime,const::rtl::OUString & rString,const com::sun::star::util::Date & aTempNullDate)1150 sal_Bool SvXMLUnitConverter::convertDateTime( double& fDateTime,
1151 const ::rtl::OUString& rString, const com::sun::star::util::Date& aTempNullDate)
1152 {
1153 com::sun::star::util::DateTime aDateTime;
1154 sal_Bool bSuccess = convertDateTime(aDateTime,rString);
1155
1156 if (bSuccess)
1157 {
1158 double fTempDateTime = 0.0;
1159 const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year);
1160 const Date aTempDate((sal_uInt16)aDateTime.Day, (sal_uInt16)aDateTime.Month, (sal_uInt16)aDateTime.Year);
1161 const sal_Int32 nTage = aTempDate - aTmpNullDate;
1162 fTempDateTime = nTage;
1163 double Hour = aDateTime.Hours;
1164 double Min = aDateTime.Minutes;
1165 double Sec = aDateTime.Seconds;
1166 double Sec100 = aDateTime.HundredthSeconds;
1167 fTempDateTime += Hour / 24;
1168 fTempDateTime += Min / (24 * 60);
1169 fTempDateTime += Sec / (24 * 60 * 60);
1170 fTempDateTime += Sec100 / (24 * 60 * 60 * 100);
1171 fDateTime = fTempDateTime;
1172 }
1173 return bSuccess;
1174 }
1175
1176 /** convert util::DateTime to ISO Date String */
convertDateTime(::rtl::OUStringBuffer & rBuffer,const com::sun::star::util::DateTime & rDateTime,sal_Bool bAddTimeIf0AM)1177 void SvXMLUnitConverter::convertDateTime(
1178 ::rtl::OUStringBuffer& rBuffer,
1179 const com::sun::star::util::DateTime& rDateTime,
1180 sal_Bool bAddTimeIf0AM )
1181 {
1182 String aString( String::CreateFromInt32( rDateTime.Year ) );
1183 aString += '-';
1184 if( rDateTime.Month < 10 )
1185 aString += '0';
1186 aString += String::CreateFromInt32( rDateTime.Month );
1187 aString += '-';
1188 if( rDateTime.Day < 10 )
1189 aString += '0';
1190 aString += String::CreateFromInt32( rDateTime.Day );
1191
1192 if( rDateTime.Seconds != 0 ||
1193 rDateTime.Minutes != 0 ||
1194 rDateTime.Hours != 0 ||
1195 bAddTimeIf0AM )
1196 {
1197 aString += 'T';
1198 if( rDateTime.Hours < 10 )
1199 aString += '0';
1200 aString += String::CreateFromInt32( rDateTime.Hours );
1201 aString += ':';
1202 if( rDateTime.Minutes < 10 )
1203 aString += '0';
1204 aString += String::CreateFromInt32( rDateTime.Minutes );
1205 aString += ':';
1206 if( rDateTime.Seconds < 10 )
1207 aString += '0';
1208 aString += String::CreateFromInt32( rDateTime.Seconds );
1209 if ( rDateTime.HundredthSeconds > 0)
1210 {
1211 aString += '.';
1212 if (rDateTime.HundredthSeconds < 10)
1213 aString += '0';
1214 aString += String::CreateFromInt32( rDateTime.HundredthSeconds );
1215 }
1216 }
1217
1218 rBuffer.append( aString );
1219 }
1220
1221 /** convert ISO Date String to util::DateTime */
convertDateTime(com::sun::star::util::DateTime & rDateTime,const::rtl::OUString & rString)1222 sal_Bool SvXMLUnitConverter::convertDateTime( com::sun::star::util::DateTime& rDateTime,
1223 const ::rtl::OUString& rString )
1224 {
1225 sal_Bool bSuccess = sal_True;
1226
1227 rtl::OUString aDateStr, aTimeStr, sDoubleStr;
1228 sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' );
1229 sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' );
1230 if (nPos2 < 0)
1231 nPos2 = rString.indexOf( (sal_Unicode) '.' );
1232 if ( nPos >= 0 )
1233 {
1234 aDateStr = rString.copy( 0, nPos );
1235 if ( nPos2 >= 0 )
1236 {
1237 aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 );
1238 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
1239 sDoubleStr += rString.copy( nPos2 + 1 );
1240 }
1241 else
1242 {
1243 aTimeStr = rString.copy(nPos + 1);
1244 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
1245 }
1246 }
1247 else
1248 aDateStr = rString; // no separator: only date part
1249
1250 sal_Int32 nYear = 1899;
1251 sal_Int32 nMonth = 12;
1252 sal_Int32 nDay = 30;
1253 sal_Int32 nHour = 0;
1254 sal_Int32 nMin = 0;
1255 sal_Int32 nSec = 0;
1256
1257 const sal_Unicode* pStr = aDateStr.getStr();
1258 sal_Int32 nDateTokens = 1;
1259 while ( *pStr )
1260 {
1261 if ( *pStr == '-' )
1262 nDateTokens++;
1263 pStr++;
1264 }
1265 if ( nDateTokens > 3 || aDateStr.getLength() == 0 )
1266 bSuccess = sal_False;
1267 else
1268 {
1269 sal_Int32 n = 0;
1270 if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) )
1271 bSuccess = sal_False;
1272 if ( nDateTokens >= 2 )
1273 if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) )
1274 bSuccess = sal_False;
1275 if ( nDateTokens >= 3 )
1276 if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) )
1277 bSuccess = sal_False;
1278 }
1279
1280 if ( aTimeStr.getLength() > 0 ) // time is optional
1281 {
1282 pStr = aTimeStr.getStr();
1283 sal_Int32 nTimeTokens = 1;
1284 while ( *pStr )
1285 {
1286 if ( *pStr == ':' )
1287 nTimeTokens++;
1288 pStr++;
1289 }
1290 if ( nTimeTokens > 3 )
1291 bSuccess = sal_False;
1292 else
1293 {
1294 sal_Int32 n = 0;
1295 if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) )
1296 bSuccess = sal_False;
1297 if ( nTimeTokens >= 2 )
1298 if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) )
1299 bSuccess = sal_False;
1300 if ( nTimeTokens >= 3 )
1301 if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) )
1302 bSuccess = sal_False;
1303 }
1304 }
1305
1306 if (bSuccess)
1307 {
1308 rDateTime.Year = (sal_uInt16)nYear;
1309 rDateTime.Month = (sal_uInt16)nMonth;
1310 rDateTime.Day = (sal_uInt16)nDay;
1311 rDateTime.Hours = (sal_uInt16)nHour;
1312 rDateTime.Minutes = (sal_uInt16)nMin;
1313 rDateTime.Seconds = (sal_uInt16)nSec;
1314 rDateTime.HundredthSeconds = (sal_uInt16)(sDoubleStr.toDouble() * 100);
1315 }
1316 return bSuccess;
1317 }
1318
1319 /** gets the position of the first comma after npos in the string
1320 rStr. Commas inside '"' pairs are not matched */
indexOfComma(const OUString & rStr,sal_Int32 nPos)1321 sal_Int32 SvXMLUnitConverter::indexOfComma( const OUString& rStr,
1322 sal_Int32 nPos )
1323 {
1324 sal_Unicode cQuote = 0;
1325 sal_Int32 nLen = rStr.getLength();
1326 for( ; nPos < nLen; nPos++ )
1327 {
1328 sal_Unicode c = rStr[nPos];
1329 switch( c )
1330 {
1331 case sal_Unicode('\''):
1332 if( 0 == cQuote )
1333 cQuote = c;
1334 else if( '\'' == cQuote )
1335 cQuote = 0;
1336 break;
1337
1338 case sal_Unicode('"'):
1339 if( 0 == cQuote )
1340 cQuote = c;
1341 else if( '\"' == cQuote )
1342 cQuote = 0;
1343 break;
1344
1345 case sal_Unicode(','):
1346 if( 0 == cQuote )
1347 return nPos;
1348 break;
1349 }
1350 }
1351
1352 return -1;
1353 }
1354
1355 // ---
1356
SvXMLTokenEnumerator(const OUString & rString,sal_Unicode cSeperator)1357 SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeperator /* = sal_Unicode(' ') */ )
1358 : maTokenString( rString ), mnNextTokenPos(0), mcSeperator( cSeperator )
1359 {
1360 }
1361
getNextToken(OUString & rToken)1362 sal_Bool SvXMLTokenEnumerator::getNextToken( OUString& rToken )
1363 {
1364 if( -1 == mnNextTokenPos )
1365 return sal_False;
1366
1367 int nTokenEndPos = maTokenString.indexOf( mcSeperator, mnNextTokenPos );
1368 if( nTokenEndPos != -1 )
1369 {
1370 rToken = maTokenString.copy( mnNextTokenPos,
1371 nTokenEndPos - mnNextTokenPos );
1372 mnNextTokenPos = nTokenEndPos + 1;
1373
1374 // if the mnNextTokenPos is at the end of the string, we have
1375 // to deliver an empty token
1376 if( mnNextTokenPos > maTokenString.getLength() )
1377 mnNextTokenPos = -1;
1378 }
1379 else
1380 {
1381 rToken = maTokenString.copy( mnNextTokenPos );
1382 mnNextTokenPos = -1;
1383 }
1384
1385 return sal_True;
1386 }
1387
1388 // ---
lcl_getPositions(const OUString & _sValue,OUString & _rContentX,OUString & _rContentY,OUString & _rContentZ)1389 bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ)
1390 {
1391 if(!_sValue.getLength() || _sValue[0] != '(')
1392 return false;
1393
1394 sal_Int32 nPos(1L);
1395 sal_Int32 nFound = _sValue.indexOf(sal_Unicode(' '), nPos);
1396
1397 if(nFound == -1 || nFound <= nPos)
1398 return false;
1399
1400 _rContentX = _sValue.copy(nPos, nFound - nPos);
1401
1402 nPos = nFound + 1;
1403 nFound = _sValue.indexOf(sal_Unicode(' '), nPos);
1404
1405 if(nFound == -1 || nFound <= nPos)
1406 return false;
1407
1408 _rContentY = _sValue.copy(nPos, nFound - nPos);
1409
1410 nPos = nFound + 1;
1411 nFound = _sValue.indexOf(sal_Unicode(')'), nPos);
1412
1413 if(nFound == -1 || nFound <= nPos)
1414 return false;
1415
1416 _rContentZ = _sValue.copy(nPos, nFound - nPos);
1417 return true;
1418
1419 }
1420 /** convert string to ::basegfx::B3DVector */
convertB3DVector(::basegfx::B3DVector & rVector,const OUString & rValue)1421 sal_Bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, const OUString& rValue )
1422 {
1423 OUString aContentX,aContentY,aContentZ;
1424 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
1425 return sal_False;
1426
1427 rtl_math_ConversionStatus eStatus;
1428
1429 rVector.setX(::rtl::math::stringToDouble(aContentX, sal_Unicode('.'),
1430 sal_Unicode(','), &eStatus, NULL));
1431
1432 if( eStatus != rtl_math_ConversionStatus_Ok )
1433 return sal_False;
1434
1435 rVector.setY(::rtl::math::stringToDouble(aContentY, sal_Unicode('.'),
1436 sal_Unicode(','), &eStatus, NULL));
1437
1438 if( eStatus != rtl_math_ConversionStatus_Ok )
1439 return sal_False;
1440
1441 rVector.setZ(::rtl::math::stringToDouble(aContentZ, sal_Unicode('.'),
1442 sal_Unicode(','), &eStatus, NULL));
1443
1444
1445 return ( eStatus == rtl_math_ConversionStatus_Ok );
1446 }
1447
1448 /** convert ::basegfx::B3DVector to string */
convertB3DVector(OUStringBuffer & rBuffer,const::basegfx::B3DVector & rVector)1449 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector )
1450 {
1451 rBuffer.append(sal_Unicode('('));
1452 convertDouble(rBuffer, rVector.getX());
1453 rBuffer.append(sal_Unicode(' '));
1454 convertDouble(rBuffer, rVector.getY());
1455 rBuffer.append(sal_Unicode(' '));
1456 convertDouble(rBuffer, rVector.getZ());
1457 rBuffer.append(sal_Unicode(')'));
1458 }
1459
1460 /** convert string to Position3D */
convertPosition3D(drawing::Position3D & rPosition,const OUString & rValue)1461 sal_Bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition,
1462 const OUString& rValue )
1463 {
1464 OUString aContentX,aContentY,aContentZ;
1465 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) )
1466 return sal_False;
1467
1468 if ( !convertDouble( rPosition.PositionX, aContentX, sal_True ) )
1469 return sal_False;
1470 if ( !convertDouble( rPosition.PositionY, aContentY, sal_True ) )
1471 return sal_False;
1472 return convertDouble( rPosition.PositionZ, aContentZ, sal_True );
1473 }
1474
1475 /** convert Position3D to string */
convertPosition3D(OUStringBuffer & rBuffer,const drawing::Position3D & rPosition)1476 void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer,
1477 const drawing::Position3D& rPosition )
1478 {
1479 rBuffer.append( sal_Unicode('(') );
1480 convertDouble( rBuffer, rPosition.PositionX, sal_True );
1481 rBuffer.append( sal_Unicode(' ') );
1482 convertDouble( rBuffer, rPosition.PositionY, sal_True );
1483 rBuffer.append( sal_Unicode(' ') );
1484 convertDouble( rBuffer, rPosition.PositionZ, sal_True );
1485 rBuffer.append( sal_Unicode(')') );
1486 }
1487
1488 const
1489 sal_Char aBase64EncodeTable[] =
1490 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1491 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1492 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1493 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1494 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1495
1496 const
1497 sal_uInt8 aBase64DecodeTable[] =
1498 { 62,255,255,255, 63, // 43-47
1499 // + /
1500
1501 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
1502 // 0 1 2 3 4 5 6 7 8 9 =
1503
1504 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
1505 // A B C D E F G H I J K L M N O
1506
1507 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1508 // P Q R S T U V W X Y Z
1509
1510 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1511 // a b c d e f g h i j k l m n o
1512
1513 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1514 // p q r s t u v w x y z
1515
1516
1517
ThreeByteToFourByte(const sal_Int8 * pBuffer,const sal_Int32 nStart,const sal_Int32 nFullLen,rtl::OUStringBuffer & sBuffer)1518 void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer)
1519 {
1520 sal_Int32 nLen(nFullLen - nStart);
1521 if (nLen > 3)
1522 nLen = 3;
1523 if (nLen == 0)
1524 {
1525 sBuffer.setLength(0);
1526 return;
1527 }
1528
1529 sal_Int32 nBinaer;
1530 switch (nLen)
1531 {
1532 case 1:
1533 {
1534 nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
1535 }
1536 break;
1537 case 2:
1538 {
1539 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1540 (((sal_uInt8)pBuffer[nStart + 1]) << 8);
1541 }
1542 break;
1543 default:
1544 {
1545 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1546 (((sal_uInt8)pBuffer[nStart + 1]) << 8) +
1547 ((sal_uInt8)pBuffer[nStart + 2]);
1548 }
1549 break;
1550 }
1551
1552 sBuffer.appendAscii("====");
1553
1554 sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
1555 sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]);
1556
1557 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
1558 sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]);
1559 if (nLen == 1)
1560 return;
1561
1562 nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
1563 sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]);
1564 if (nLen == 2)
1565 return;
1566
1567 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
1568 sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]);
1569 }
1570
encodeBase64(rtl::OUStringBuffer & aStrBuffer,const uno::Sequence<sal_Int8> & aPass)1571 void SvXMLUnitConverter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
1572 {
1573 sal_Int32 i(0);
1574 sal_Int32 nBufferLength(aPass.getLength());
1575 const sal_Int8* pBuffer = aPass.getConstArray();
1576 while (i < nBufferLength)
1577 {
1578 rtl::OUStringBuffer sBuffer;
1579 ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer);
1580 aStrBuffer.append(sBuffer);
1581 i += 3;
1582 }
1583 }
1584
decodeBase64(uno::Sequence<sal_Int8> & aBuffer,const rtl::OUString & sBuffer)1585 void SvXMLUnitConverter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer)
1586 {
1587 sal_Int32 nCharsDecoded = decodeBase64SomeChars( aBuffer, sBuffer );
1588 OSL_ENSURE( nCharsDecoded == sBuffer.getLength(),
1589 "some bytes left in base64 decoding!" );
1590 (void)nCharsDecoded;
1591 }
1592
decodeBase64SomeChars(uno::Sequence<sal_Int8> & rOutBuffer,const rtl::OUString & rInBuffer)1593 sal_Int32 SvXMLUnitConverter::decodeBase64SomeChars(
1594 uno::Sequence<sal_Int8>& rOutBuffer,
1595 const rtl::OUString& rInBuffer)
1596 {
1597 sal_Int32 nInBufferLen = rInBuffer.getLength();
1598 sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
1599 if( rOutBuffer.getLength() < nMinOutBufferLen )
1600 rOutBuffer.realloc( nMinOutBufferLen );
1601
1602 const sal_Unicode *pInBuffer = rInBuffer.getStr();
1603 sal_Int8 *pOutBuffer = rOutBuffer.getArray();
1604 sal_Int8 *pOutBufferStart = pOutBuffer;
1605 sal_Int32 nCharsDecoded = 0;
1606
1607 sal_uInt8 aDecodeBuffer[4];
1608 sal_Int32 nBytesToDecode = 0;
1609 sal_Int32 nBytesGotFromDecoding = 3;
1610 sal_Int32 nInBufferPos= 0;
1611 while( nInBufferPos < nInBufferLen )
1612 {
1613 sal_Unicode cChar = *pInBuffer;
1614 if( cChar >= '+' && cChar <= 'z' )
1615 {
1616 sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
1617 if( nByte != 255 )
1618 {
1619 // We have found a valid character!
1620 aDecodeBuffer[nBytesToDecode++] = nByte;
1621
1622 // One '=' character at the end means 2 out bytes
1623 // Two '=' characters at the end mean 1 out bytes
1624 if( '=' == cChar && nBytesToDecode > 2 )
1625 nBytesGotFromDecoding--;
1626 if( 4 == nBytesToDecode )
1627 {
1628 // Four characters found, so we may convert now!
1629 sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
1630 (aDecodeBuffer[1] << 12) +
1631 (aDecodeBuffer[2] << 6) +
1632 aDecodeBuffer[3];
1633
1634 *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16);
1635 if( nBytesGotFromDecoding > 1 )
1636 *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8);
1637 if( nBytesGotFromDecoding > 2 )
1638 *pOutBuffer++ = (sal_Int8)(nOut & 0xff);
1639 nCharsDecoded = nInBufferPos + 1;
1640 nBytesToDecode = 0;
1641 nBytesGotFromDecoding = 3;
1642 }
1643 }
1644 else
1645 {
1646 nCharsDecoded++;
1647 }
1648 }
1649 else
1650 {
1651 nCharsDecoded++;
1652 }
1653
1654 nInBufferPos++;
1655 pInBuffer++;
1656 }
1657 if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
1658 rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
1659
1660 return nCharsDecoded;
1661 }
1662
convertNumFormat(sal_Int16 & rType,const OUString & rNumFmt,const OUString & rNumLetterSync,sal_Bool bNumberNone) const1663 sal_Bool SvXMLUnitConverter::convertNumFormat(
1664 sal_Int16& rType,
1665 const OUString& rNumFmt,
1666 const OUString& rNumLetterSync,
1667 sal_Bool bNumberNone ) const
1668 {
1669 sal_Bool bRet = sal_True;
1670 sal_Bool bExt = sal_False;
1671
1672 sal_Int32 nLen = rNumFmt.getLength();
1673 if( 0 == nLen )
1674 {
1675 if( bNumberNone )
1676 rType = NumberingType::NUMBER_NONE;
1677 else
1678 bRet = sal_False;
1679 }
1680 else if( 1 == nLen )
1681 {
1682 switch( rNumFmt[0] )
1683 {
1684 case sal_Unicode('1'): rType = NumberingType::ARABIC; break;
1685 case sal_Unicode('a'): rType = NumberingType::CHARS_LOWER_LETTER; break;
1686 case sal_Unicode('A'): rType = NumberingType::CHARS_UPPER_LETTER; break;
1687 case sal_Unicode('i'): rType = NumberingType::ROMAN_LOWER; break;
1688 case sal_Unicode('I'): rType = NumberingType::ROMAN_UPPER; break;
1689 default: bExt = sal_True; break;
1690 }
1691 if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) )
1692 {
1693 switch( rType )
1694 {
1695 case NumberingType::CHARS_LOWER_LETTER:
1696 rType = NumberingType::CHARS_LOWER_LETTER_N;
1697 break;
1698 case NumberingType::CHARS_UPPER_LETTER:
1699 rType = NumberingType::CHARS_UPPER_LETTER_N;
1700 break;
1701 }
1702 }
1703 }
1704 else
1705 {
1706 bExt = sal_True;
1707 }
1708 if( bExt )
1709 {
1710 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
1711 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) )
1712 {
1713 rType = xInfo->getNumberingType( rNumFmt );
1714 }
1715 else
1716 {
1717 rType = NumberingType::ARABIC;
1718 }
1719 }
1720
1721 return bRet;
1722 }
1723
convertNumFormat(OUStringBuffer & rBuffer,sal_Int16 nType) const1724 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer,
1725 sal_Int16 nType ) const
1726 {
1727 enum XMLTokenEnum eFormat = XML_TOKEN_INVALID;
1728 sal_Bool bExt = sal_False;
1729 switch( nType )
1730 {
1731 case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break;
1732 case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break;
1733 case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break;
1734 case NumberingType::ROMAN_LOWER: eFormat = XML_I; break;
1735 case NumberingType::ARABIC: eFormat = XML_1; break;
1736 case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break;
1737 case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break;
1738 case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break;
1739
1740 case NumberingType::CHAR_SPECIAL:
1741 case NumberingType::PAGE_DESCRIPTOR:
1742 case NumberingType::BITMAP:
1743 DBG_ASSERT( eFormat != XML_TOKEN_INVALID, "invalid number format" );
1744 break;
1745 default:
1746 bExt = sal_True;
1747 break;
1748 }
1749
1750 if( eFormat != XML_TOKEN_INVALID )
1751 {
1752 rBuffer.append( GetXMLToken(eFormat) );
1753 }
1754 else
1755 {
1756 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo();
1757 if( xInfo.is() )
1758 rBuffer.append( xInfo->getNumberingIdentifier( nType ) );
1759 }
1760 }
1761
convertNumLetterSync(OUStringBuffer & rBuffer,sal_Int16 nType) const1762 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer,
1763 sal_Int16 nType ) const
1764 {
1765 enum XMLTokenEnum eSync = XML_TOKEN_INVALID;
1766 switch( nType )
1767 {
1768 case NumberingType::CHARS_UPPER_LETTER:
1769 case NumberingType::CHARS_LOWER_LETTER:
1770 case NumberingType::ROMAN_UPPER:
1771 case NumberingType::ROMAN_LOWER:
1772 case NumberingType::ARABIC:
1773 case NumberingType::NUMBER_NONE:
1774 // default
1775 // eSync = XML_FALSE;
1776 break;
1777
1778 case NumberingType::CHARS_UPPER_LETTER_N:
1779 case NumberingType::CHARS_LOWER_LETTER_N:
1780 eSync = XML_TRUE;
1781 break;
1782
1783 case NumberingType::CHAR_SPECIAL:
1784 case NumberingType::PAGE_DESCRIPTOR:
1785 case NumberingType::BITMAP:
1786 DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" );
1787 break;
1788 }
1789 if( eSync != XML_TOKEN_INVALID )
1790 rBuffer.append( GetXMLToken(eSync) );
1791 }
1792
convertPropertySet(uno::Sequence<beans::PropertyValue> & rProps,const uno::Reference<beans::XPropertySet> & aProperties)1793 void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps,
1794 const uno::Reference<beans::XPropertySet>& aProperties)
1795 {
1796 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo();
1797 if (xPropertySetInfo.is())
1798 {
1799 uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties();
1800 const sal_Int32 nCount(aProps.getLength());
1801 if (nCount)
1802 {
1803 rProps.realloc(nCount);
1804 beans::PropertyValue* pProps = rProps.getArray();
1805 for (sal_Int32 i = 0; i < nCount; i++, ++pProps)
1806 {
1807 pProps->Name = aProps[i].Name;
1808 pProps->Value = aProperties->getPropertyValue(aProps[i].Name);
1809 }
1810 }
1811 }
1812 }
1813
convertPropertySet(uno::Reference<beans::XPropertySet> & rProperties,const uno::Sequence<beans::PropertyValue> & aProps)1814 void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet>& rProperties,
1815 const uno::Sequence<beans::PropertyValue>& aProps)
1816 {
1817 sal_Int32 nCount(aProps.getLength());
1818 if (nCount)
1819 {
1820 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo();
1821 if (xPropertySetInfo.is())
1822 {
1823 for (sal_Int32 i = 0; i < nCount; i++)
1824 {
1825 if (xPropertySetInfo->hasPropertyByName(aProps[i].Name))
1826 rProperties->setPropertyValue(aProps[i].Name, aProps[i].Value);
1827 }
1828 }
1829 }
1830 }
1831
clearUndefinedChars(rtl::OUString & rTarget,const rtl::OUString & rSource)1832 void SvXMLUnitConverter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource)
1833 {
1834 sal_uInt32 nLength(rSource.getLength());
1835 rtl::OUStringBuffer sBuffer(nLength);
1836 for (sal_uInt32 i = 0; i < nLength; i++)
1837 {
1838 sal_Unicode cChar = rSource[i];
1839 if (!(cChar < 0x0020) ||
1840 (cChar == 0x0009) || // TAB
1841 (cChar == 0x000A) || // LF
1842 (cChar == 0x000D)) // legal character
1843 sBuffer.append(cChar);
1844 }
1845 rTarget = sBuffer.makeStringAndClear();
1846 }
1847
encodeStyleName(const OUString & rName,sal_Bool * pEncoded) const1848 OUString SvXMLUnitConverter::encodeStyleName(
1849 const OUString& rName,
1850 sal_Bool *pEncoded ) const
1851 {
1852 if( pEncoded )
1853 *pEncoded = sal_False;
1854
1855 sal_Int32 nLen = rName.getLength();
1856 OUStringBuffer aBuffer( nLen );
1857
1858 for( sal_Int32 i = 0; i < nLen; i++ )
1859 {
1860 sal_Unicode c = rName[i];
1861 sal_Bool bValidChar = sal_False;
1862 if( c < 0x00ffU )
1863 {
1864 bValidChar =
1865 (c >= 0x0041 && c <= 0x005a) ||
1866 (c >= 0x0061 && c <= 0x007a) ||
1867 (c >= 0x00c0 && c <= 0x00d6) ||
1868 (c >= 0x00d8 && c <= 0x00f6) ||
1869 (c >= 0x00f8 && c <= 0x00ff) ||
1870 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) ||
1871 c == 0x00b7 || c == '-' || c == '.') );
1872 }
1873 else
1874 {
1875 if( (c >= 0xf900U && c <= 0xfffeU) ||
1876 (c >= 0x20ddU && c <= 0x20e0U))
1877 {
1878 bValidChar = sal_False;
1879 }
1880 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 ||
1881 c == 0x06e5 || c == 0x06e6 )
1882 {
1883 bValidChar = sal_True;
1884 }
1885 else if( c == 0x0387 )
1886 {
1887 bValidChar = i > 0;
1888 }
1889 else
1890 {
1891 if( !xCharClass.is() )
1892 {
1893 if( mxServiceFactory.is() )
1894 {
1895 try
1896 {
1897 const_cast < SvXMLUnitConverter * >(this)
1898 ->xCharClass =
1899 Reference < XCharacterClassification >(
1900 mxServiceFactory->createInstance(
1901 OUString::createFromAscii(
1902 "com.sun.star.i18n.CharacterClassification_Unicode") ),
1903 UNO_QUERY );
1904
1905 OSL_ENSURE( xCharClass.is(),
1906 "can't instantiate character clossification component" );
1907 }
1908 catch( com::sun::star::uno::Exception& )
1909 {
1910 }
1911 }
1912 }
1913 if( xCharClass.is() )
1914 {
1915 sal_Int16 nType = xCharClass->getType( rName, i );
1916
1917 switch( nType )
1918 {
1919 case UnicodeType::UPPERCASE_LETTER: // Lu
1920 case UnicodeType::LOWERCASE_LETTER: // Ll
1921 case UnicodeType::TITLECASE_LETTER: // Lt
1922 case UnicodeType::OTHER_LETTER: // Lo
1923 case UnicodeType::LETTER_NUMBER: // Nl
1924 bValidChar = sal_True;
1925 break;
1926 case UnicodeType::NON_SPACING_MARK: // Ms
1927 case UnicodeType::ENCLOSING_MARK: // Me
1928 case UnicodeType::COMBINING_SPACING_MARK: //Mc
1929 case UnicodeType::MODIFIER_LETTER: // Lm
1930 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd
1931 bValidChar = i > 0;
1932 break;
1933 }
1934 }
1935 }
1936 }
1937 if( bValidChar )
1938 {
1939 aBuffer.append( c );
1940 }
1941 else
1942 {
1943 aBuffer.append( static_cast< sal_Unicode >( '_' ) );
1944 if( c > 0x0fff )
1945 aBuffer.append( static_cast< sal_Unicode >(
1946 aHexTab[ (c >> 12) & 0x0f ] ) );
1947 if( c > 0x00ff )
1948 aBuffer.append( static_cast< sal_Unicode >(
1949 aHexTab[ (c >> 8) & 0x0f ] ) );
1950 if( c > 0x000f )
1951 aBuffer.append( static_cast< sal_Unicode >(
1952 aHexTab[ (c >> 4) & 0x0f ] ) );
1953 aBuffer.append( static_cast< sal_Unicode >(
1954 aHexTab[ c & 0x0f ] ) );
1955 aBuffer.append( static_cast< sal_Unicode >( '_' ) );
1956 if( pEncoded )
1957 *pEncoded = sal_True;
1958 }
1959 }
1960
1961 // check for length
1962 if( aBuffer.getLength() > ((1<<15)-1) )
1963 {
1964 aBuffer = rName;
1965 if( pEncoded )
1966 *pEncoded = sal_False;
1967 }
1968
1969
1970 return aBuffer.makeStringAndClear();
1971 }
1972
1973 // static
convertTimeDuration(const Time & rTime,sal_Int32 nSecondsFraction)1974 rtl::OUString SvXMLUnitConverter::convertTimeDuration( const Time& rTime, sal_Int32 nSecondsFraction )
1975 {
1976 // return ISO time period string
1977 rtl::OUStringBuffer sTmp;
1978 sTmp.append( sal_Unicode('P') ); // "period"
1979
1980 sal_uInt16 nHours = rTime.GetHour();
1981 sal_Bool bHasHours = ( nHours > 0 );
1982 if ( nHours >= 24 )
1983 {
1984 // add days
1985
1986 sal_uInt16 nDays = nHours / 24;
1987 sTmp.append( (sal_Int32) nDays );
1988 sTmp.append( sal_Unicode('D') ); // "days"
1989
1990 nHours -= nDays * 24;
1991 }
1992 sTmp.append( sal_Unicode('T') ); // "time"
1993
1994 if ( bHasHours )
1995 {
1996 sTmp.append( (sal_Int32) nHours );
1997 sTmp.append( sal_Unicode('H') ); // "hours"
1998 }
1999 sal_uInt16 nMinutes = rTime.GetMin();
2000 if ( bHasHours || nMinutes > 0 )
2001 {
2002 sTmp.append( (sal_Int32) nMinutes );
2003 sTmp.append( sal_Unicode('M') ); // "minutes"
2004 }
2005 sal_uInt16 nSeconds = rTime.GetSec();
2006 sTmp.append( (sal_Int32) nSeconds );
2007 if ( nSecondsFraction )
2008 {
2009 sTmp.append( sal_Unicode( '.' ) );
2010 ::rtl::OUStringBuffer aFractional;
2011 convertNumber( aFractional, nSecondsFraction );
2012 sTmp.append( aFractional.getStr() );
2013 }
2014 sTmp.append( sal_Unicode('S') ); // "seconds"
2015
2016 return sTmp.makeStringAndClear();
2017 }
2018
2019 // static
convertTimeDuration(const rtl::OUString & rString,Time & rTime,sal_Int32 * pSecondsFraction)2020 bool SvXMLUnitConverter::convertTimeDuration( const rtl::OUString& rString, Time& rTime, sal_Int32* pSecondsFraction )
2021 {
2022 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
2023 const sal_Unicode* pStr = aTrimmed.getStr();
2024
2025 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
2026 return false;
2027
2028 bool bSuccess = true;
2029 sal_Bool bDone = sal_False;
2030 sal_Bool bTimePart = sal_False;
2031 sal_Bool bFractional = sal_False;
2032 sal_Int32 nDays = 0;
2033 sal_Int32 nHours = 0;
2034 sal_Int32 nMins = 0;
2035 sal_Int32 nSecs = 0;
2036 sal_Int32 nTemp = 0;
2037 sal_Int32 nSecondsFraction = 0;
2038
2039 while ( bSuccess && !bDone )
2040 {
2041 sal_Unicode c = *(pStr++);
2042 if ( !c ) // end
2043 bDone = sal_True;
2044 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
2045 {
2046 if ( bFractional )
2047 {
2048 if ( nSecondsFraction >= SAL_MAX_INT32 / 10 )
2049 bSuccess = false;
2050 else
2051 {
2052 nSecondsFraction *= 10;
2053 nSecondsFraction += (c - sal_Unicode('0'));
2054 }
2055 }
2056 else
2057 {
2058 if ( nTemp >= SAL_MAX_INT32 / 10 )
2059 bSuccess = false;
2060 else
2061 {
2062 nTemp *= 10;
2063 nTemp += (c - sal_Unicode('0'));
2064 }
2065 }
2066 }
2067 else if ( bTimePart )
2068 {
2069 if ( c == sal_Unicode('H') )
2070 {
2071 nHours = nTemp;
2072 nTemp = 0;
2073 }
2074 else if ( c == sal_Unicode('M') )
2075 {
2076 nMins = nTemp;
2077 nTemp = 0;
2078 }
2079 else if ( c == sal_Unicode('S') )
2080 {
2081 nSecs = nTemp;
2082 nTemp = 0;
2083 }
2084 else if ( c == '.' )
2085 {
2086 bFractional = sal_True;
2087 }
2088 else
2089 bSuccess = false; // invalid characted
2090 }
2091 else
2092 {
2093 if ( c == sal_Unicode('T') ) // "T" starts time part
2094 bTimePart = sal_True;
2095 else if ( c == sal_Unicode('D') )
2096 {
2097 nDays = nTemp;
2098 nTemp = 0;
2099 }
2100 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
2101 {
2102 //! how many days is a year or month?
2103
2104 DBG_ERROR("years or months in duration: not implemented");
2105 bSuccess = false;
2106 }
2107 else
2108 bSuccess = false; // invalid characted
2109 }
2110 }
2111
2112 if ( bSuccess )
2113 {
2114 if ( nDays )
2115 nHours += nDays * 24; // add the days to the hours part
2116 rTime = Time( nHours, nMins, nSecs );
2117 if ( pSecondsFraction )
2118 *pSecondsFraction = nSecondsFraction % 1000;
2119 }
2120 return bSuccess;
2121 }
2122
convertAny(::rtl::OUStringBuffer & sValue,::rtl::OUStringBuffer & sType,const com::sun::star::uno::Any & aValue)2123 sal_Bool SvXMLUnitConverter::convertAny( ::rtl::OUStringBuffer& sValue,
2124 ::rtl::OUStringBuffer& sType ,
2125 const com::sun::star::uno::Any& aValue)
2126 {
2127 sal_Bool bConverted = sal_False;
2128
2129 sValue.setLength(0);
2130 sType.setLength (0);
2131
2132 switch(aValue.getValueTypeClass())
2133 {
2134 case com::sun::star::uno::TypeClass_BYTE :
2135 case com::sun::star::uno::TypeClass_SHORT :
2136 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT :
2137 case com::sun::star::uno::TypeClass_LONG :
2138 case com::sun::star::uno::TypeClass_UNSIGNED_LONG :
2139 {
2140 sal_Int32 nTempValue = 0;
2141 if (aValue >>= nTempValue)
2142 {
2143 sType.appendAscii("integer");
2144 bConverted = sal_True;
2145 SvXMLUnitConverter::convertNumber(sValue, nTempValue);
2146 }
2147 }
2148 break;
2149
2150 case com::sun::star::uno::TypeClass_BOOLEAN :
2151 {
2152 sal_Bool bTempValue = sal_False;
2153 if (aValue >>= bTempValue)
2154 {
2155 sType.appendAscii("boolean");
2156 bConverted = sal_True;
2157 SvXMLUnitConverter::convertBool(sValue, bTempValue);
2158 }
2159 }
2160 break;
2161
2162 case com::sun::star::uno::TypeClass_FLOAT :
2163 case com::sun::star::uno::TypeClass_DOUBLE :
2164 {
2165 double fTempValue = 0.0;
2166 if (aValue >>= fTempValue)
2167 {
2168 sType.appendAscii("float");
2169 bConverted = sal_True;
2170 SvXMLUnitConverter::convertDouble(sValue, fTempValue);
2171 }
2172 }
2173 break;
2174
2175 case com::sun::star::uno::TypeClass_STRING :
2176 {
2177 ::rtl::OUString sTempValue;
2178 if (aValue >>= sTempValue)
2179 {
2180 sType.appendAscii("string");
2181 bConverted = sal_True;
2182 sValue.append(sTempValue);
2183 }
2184 }
2185 break;
2186
2187 case com::sun::star::uno::TypeClass_STRUCT :
2188 {
2189 com::sun::star::util::Date aDate ;
2190 com::sun::star::util::Time aTime ;
2191 com::sun::star::util::DateTime aDateTime;
2192
2193 if (aValue >>= aDate)
2194 {
2195 sType.appendAscii("date");
2196 bConverted = sal_True;
2197 com::sun::star::util::DateTime aTempValue;
2198 aTempValue.Day = aDate.Day;
2199 aTempValue.Month = aDate.Month;
2200 aTempValue.Year = aDate.Year;
2201 aTempValue.HundredthSeconds = 0;
2202 aTempValue.Seconds = 0;
2203 aTempValue.Minutes = 0;
2204 aTempValue.Hours = 0;
2205 SvXMLUnitConverter::convertDateTime(sValue, aTempValue);
2206 }
2207 else
2208 if (aValue >>= aTime)
2209 {
2210 sType.appendAscii("time");
2211 bConverted = sal_True;
2212 com::sun::star::util::DateTime aTempValue;
2213 aTempValue.Day = 0;
2214 aTempValue.Month = 0;
2215 aTempValue.Year = 0;
2216 aTempValue.HundredthSeconds = aTime.HundredthSeconds;
2217 aTempValue.Seconds = aTime.Seconds;
2218 aTempValue.Minutes = aTime.Minutes;
2219 aTempValue.Hours = aTime.Hours;
2220 SvXMLUnitConverter::convertTime(sValue, aTempValue);
2221 }
2222 else
2223 if (aValue >>= aDateTime)
2224 {
2225 sType.appendAscii("date");
2226 bConverted = sal_True;
2227 SvXMLUnitConverter::convertDateTime(sValue, aDateTime);
2228 }
2229 }
2230 break;
2231 default:
2232 break;
2233 }
2234
2235 return bConverted;
2236 }
2237
convertAny(com::sun::star::uno::Any & aValue,const::rtl::OUString & sType,const::rtl::OUString & sValue)2238 sal_Bool SvXMLUnitConverter::convertAny( com::sun::star::uno::Any& aValue,
2239 const ::rtl::OUString& sType ,
2240 const ::rtl::OUString& sValue)
2241 {
2242 sal_Bool bConverted = sal_False;
2243
2244 if (sType.equalsAscii("boolean"))
2245 {
2246 sal_Bool bTempValue = sal_False;
2247 SvXMLUnitConverter::convertBool(bTempValue, sValue);
2248 aValue <<= bTempValue;
2249 bConverted = sal_True;
2250 }
2251 else
2252 if (sType.equalsAscii("integer"))
2253 {
2254 sal_Int32 nTempValue = 0;
2255 SvXMLUnitConverter::convertNumber(nTempValue, sValue);
2256 aValue <<= nTempValue;
2257 bConverted = sal_True;
2258 }
2259 else
2260 if (sType.equalsAscii("float"))
2261 {
2262 double fTempValue = 0.0;
2263 SvXMLUnitConverter::convertDouble(fTempValue, sValue);
2264 aValue <<= fTempValue;
2265 bConverted = sal_True;
2266 }
2267 else
2268 if (sType.equalsAscii("string"))
2269 {
2270 aValue <<= sValue;
2271 bConverted = sal_True;
2272 }
2273 else
2274 if (sType.equalsAscii("date"))
2275 {
2276 com::sun::star::util::DateTime aTempValue;
2277 SvXMLUnitConverter::convertDateTime(aTempValue, sValue);
2278 aValue <<= aTempValue;
2279 bConverted = sal_True;
2280 }
2281 else
2282 if (sType.equalsAscii("time"))
2283 {
2284 com::sun::star::util::DateTime aTempValue;
2285 com::sun::star::util::Time aConvValue;
2286 SvXMLUnitConverter::convertTime(aTempValue, sValue);
2287 aConvValue.HundredthSeconds = aTempValue.HundredthSeconds;
2288 aConvValue.Seconds = aTempValue.Seconds;
2289 aConvValue.Minutes = aTempValue.Minutes;
2290 aConvValue.Hours = aTempValue.Hours;
2291 aValue <<= aConvValue;
2292 bConverted = sal_True;
2293 }
2294
2295 return bConverted;
2296 }
2297