xref: /trunk/main/xmloff/source/core/xmluconv.cxx (revision 63bba73c)
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