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