xref: /AOO41X/main/sax/source/tools/converter.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1*cdf0e10cSrcweir /*************************************************************************
2*cdf0e10cSrcweir  *
3*cdf0e10cSrcweir  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4*cdf0e10cSrcweir  *
5*cdf0e10cSrcweir  * Copyright 2000, 2010 Oracle and/or its affiliates.
6*cdf0e10cSrcweir  *
7*cdf0e10cSrcweir  * OpenOffice.org - a multi-platform office productivity suite
8*cdf0e10cSrcweir  *
9*cdf0e10cSrcweir  * This file is part of OpenOffice.org.
10*cdf0e10cSrcweir  *
11*cdf0e10cSrcweir  * OpenOffice.org is free software: you can redistribute it and/or modify
12*cdf0e10cSrcweir  * it under the terms of the GNU Lesser General Public License version 3
13*cdf0e10cSrcweir  * only, as published by the Free Software Foundation.
14*cdf0e10cSrcweir  *
15*cdf0e10cSrcweir  * OpenOffice.org is distributed in the hope that it will be useful,
16*cdf0e10cSrcweir  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17*cdf0e10cSrcweir  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18*cdf0e10cSrcweir  * GNU Lesser General Public License version 3 for more details
19*cdf0e10cSrcweir  * (a copy is included in the LICENSE file that accompanied this code).
20*cdf0e10cSrcweir  *
21*cdf0e10cSrcweir  * You should have received a copy of the GNU Lesser General Public License
22*cdf0e10cSrcweir  * version 3 along with OpenOffice.org.  If not, see
23*cdf0e10cSrcweir  * <http://www.openoffice.org/license.html>
24*cdf0e10cSrcweir  * for a copy of the LGPLv3 License.
25*cdf0e10cSrcweir  *
26*cdf0e10cSrcweir  ************************************************************************/
27*cdf0e10cSrcweir 
28*cdf0e10cSrcweir 
29*cdf0e10cSrcweir #include <com/sun/star/i18n/UnicodeType.hpp>
30*cdf0e10cSrcweir #include <com/sun/star/util/DateTime.hpp>
31*cdf0e10cSrcweir #include <com/sun/star/util/Date.hpp>
32*cdf0e10cSrcweir #include <com/sun/star/util/Duration.hpp>
33*cdf0e10cSrcweir #include <com/sun/star/uno/Sequence.hxx>
34*cdf0e10cSrcweir 
35*cdf0e10cSrcweir #include <rtl/ustrbuf.hxx>
36*cdf0e10cSrcweir #include <rtl/math.hxx>
37*cdf0e10cSrcweir #include "sax/tools/converter.hxx"
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir using namespace rtl;
40*cdf0e10cSrcweir using namespace com::sun::star;
41*cdf0e10cSrcweir using namespace com::sun::star::uno;
42*cdf0e10cSrcweir using namespace com::sun::star::util;
43*cdf0e10cSrcweir //using namespace com::sun::star::text;
44*cdf0e10cSrcweir //using namespace com::sun::star::style;
45*cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
46*cdf0e10cSrcweir 
47*cdf0e10cSrcweir namespace sax {
48*cdf0e10cSrcweir 
49*cdf0e10cSrcweir static const sal_Char* gpsMM = "mm";
50*cdf0e10cSrcweir static const sal_Char* gpsCM = "cm";
51*cdf0e10cSrcweir static const sal_Char* gpsPT = "pt";
52*cdf0e10cSrcweir static const sal_Char* gpsINCH = "in";
53*cdf0e10cSrcweir static const sal_Char* gpsPC = "pc";
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
56*cdf0e10cSrcweir const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6;
57*cdf0e10cSrcweir #define XML_NULLDATE "NullDate"
58*cdf0e10cSrcweir 
59*cdf0e10cSrcweir /** convert string to measure using optional min and max values*/
60*cdf0e10cSrcweir bool Converter::convertMeasure(	sal_Int32& rValue,
61*cdf0e10cSrcweir 								const OUString& rString,
62*cdf0e10cSrcweir 								sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
63*cdf0e10cSrcweir 								sal_Int32 nMin /* = SAL_MIN_INT32 */,
64*cdf0e10cSrcweir 								sal_Int32 nMax /* = SAL_MAX_INT32 */ )
65*cdf0e10cSrcweir {
66*cdf0e10cSrcweir     bool bNeg = false;
67*cdf0e10cSrcweir     double nVal = 0;
68*cdf0e10cSrcweir 
69*cdf0e10cSrcweir     sal_Int32 nPos = 0;
70*cdf0e10cSrcweir     sal_Int32 nLen = rString.getLength();
71*cdf0e10cSrcweir 
72*cdf0e10cSrcweir     // skip white space
73*cdf0e10cSrcweir     while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
74*cdf0e10cSrcweir         nPos++;
75*cdf0e10cSrcweir 
76*cdf0e10cSrcweir     if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
77*cdf0e10cSrcweir     {
78*cdf0e10cSrcweir         bNeg = true;
79*cdf0e10cSrcweir         nPos++;
80*cdf0e10cSrcweir     }
81*cdf0e10cSrcweir 
82*cdf0e10cSrcweir     // get number
83*cdf0e10cSrcweir     while( nPos < nLen &&
84*cdf0e10cSrcweir            sal_Unicode('0') <= rString[nPos] &&
85*cdf0e10cSrcweir            sal_Unicode('9') >= rString[nPos] )
86*cdf0e10cSrcweir     {
87*cdf0e10cSrcweir         // TODO: check overflow!
88*cdf0e10cSrcweir         nVal *= 10;
89*cdf0e10cSrcweir         nVal += (rString[nPos] - sal_Unicode('0'));
90*cdf0e10cSrcweir         nPos++;
91*cdf0e10cSrcweir     }
92*cdf0e10cSrcweir     double nDiv = 1.;
93*cdf0e10cSrcweir     if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
94*cdf0e10cSrcweir     {
95*cdf0e10cSrcweir         nPos++;
96*cdf0e10cSrcweir 
97*cdf0e10cSrcweir         while( nPos < nLen &&
98*cdf0e10cSrcweir                sal_Unicode('0') <= rString[nPos] &&
99*cdf0e10cSrcweir                sal_Unicode('9') >= rString[nPos] )
100*cdf0e10cSrcweir         {
101*cdf0e10cSrcweir             // TODO: check overflow!
102*cdf0e10cSrcweir             nDiv *= 10;
103*cdf0e10cSrcweir             nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv );
104*cdf0e10cSrcweir             nPos++;
105*cdf0e10cSrcweir         }
106*cdf0e10cSrcweir     }
107*cdf0e10cSrcweir 
108*cdf0e10cSrcweir     // skip white space
109*cdf0e10cSrcweir     while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
110*cdf0e10cSrcweir         nPos++;
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir     if( nPos < nLen )
113*cdf0e10cSrcweir     {
114*cdf0e10cSrcweir 
115*cdf0e10cSrcweir 		if( MeasureUnit::PERCENT == nTargetUnit )
116*cdf0e10cSrcweir         {
117*cdf0e10cSrcweir             if( sal_Unicode('%') != rString[nPos] )
118*cdf0e10cSrcweir                 return false;
119*cdf0e10cSrcweir         }
120*cdf0e10cSrcweir 		else if( MeasureUnit::PIXEL == nTargetUnit )
121*cdf0e10cSrcweir         {
122*cdf0e10cSrcweir             if( nPos + 1 >= nLen ||
123*cdf0e10cSrcweir                 (sal_Unicode('p') != rString[nPos] &&
124*cdf0e10cSrcweir                  sal_Unicode('P') != rString[nPos])||
125*cdf0e10cSrcweir                 (sal_Unicode('x') != rString[nPos+1] &&
126*cdf0e10cSrcweir                  sal_Unicode('X') != rString[nPos+1]) )
127*cdf0e10cSrcweir                 return false;
128*cdf0e10cSrcweir         }
129*cdf0e10cSrcweir         else
130*cdf0e10cSrcweir         {
131*cdf0e10cSrcweir             OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
132*cdf0e10cSrcweir                         MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported");
133*cdf0e10cSrcweir             const sal_Char *aCmpsL[2] = { 0, 0 };
134*cdf0e10cSrcweir             const sal_Char *aCmpsU[2] = { 0, 0 };
135*cdf0e10cSrcweir             double aScales[2] = { 1., 1. };
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir             if( MeasureUnit::TWIP == nTargetUnit )
138*cdf0e10cSrcweir             {
139*cdf0e10cSrcweir                 switch( rString[nPos] )
140*cdf0e10cSrcweir                 {
141*cdf0e10cSrcweir                 case sal_Unicode('c'):
142*cdf0e10cSrcweir                 case sal_Unicode('C'):
143*cdf0e10cSrcweir                     aCmpsL[0] = "cm";
144*cdf0e10cSrcweir                     aCmpsU[0] = "CM";
145*cdf0e10cSrcweir                     aScales[0] = (72.*20.)/2.54; // twip
146*cdf0e10cSrcweir                     break;
147*cdf0e10cSrcweir                 case sal_Unicode('i'):
148*cdf0e10cSrcweir                 case sal_Unicode('I'):
149*cdf0e10cSrcweir                     aCmpsL[0] = "in";
150*cdf0e10cSrcweir                     aCmpsU[0] = "IN";
151*cdf0e10cSrcweir                     aScales[0] = 72.*20.; // twip
152*cdf0e10cSrcweir                     break;
153*cdf0e10cSrcweir                 case sal_Unicode('m'):
154*cdf0e10cSrcweir                 case sal_Unicode('M'):
155*cdf0e10cSrcweir                     aCmpsL[0] = "mm";
156*cdf0e10cSrcweir                     aCmpsU[0] = "MM";
157*cdf0e10cSrcweir                     aScales[0] = (72.*20.)/25.4; // twip
158*cdf0e10cSrcweir                     break;
159*cdf0e10cSrcweir                 case sal_Unicode('p'):
160*cdf0e10cSrcweir                 case sal_Unicode('P'):
161*cdf0e10cSrcweir                     aCmpsL[0] = "pt";
162*cdf0e10cSrcweir                     aCmpsU[0] = "PT";
163*cdf0e10cSrcweir                     aScales[0] = 20.; // twip
164*cdf0e10cSrcweir 
165*cdf0e10cSrcweir                     aCmpsL[1] = "pc";
166*cdf0e10cSrcweir                     aCmpsU[1] = "PC";
167*cdf0e10cSrcweir                     aScales[1] = 12.*20.; // twip
168*cdf0e10cSrcweir                     break;
169*cdf0e10cSrcweir                 }
170*cdf0e10cSrcweir             }
171*cdf0e10cSrcweir             else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
172*cdf0e10cSrcweir             {
173*cdf0e10cSrcweir 				double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0;
174*cdf0e10cSrcweir                 switch( rString[nPos] )
175*cdf0e10cSrcweir                 {
176*cdf0e10cSrcweir                 case sal_Unicode('c'):
177*cdf0e10cSrcweir                 case sal_Unicode('C'):
178*cdf0e10cSrcweir                     aCmpsL[0] = "cm";
179*cdf0e10cSrcweir                     aCmpsU[0] = "CM";
180*cdf0e10cSrcweir                     aScales[0] = 10.0 * nScaleFactor; // mm/100
181*cdf0e10cSrcweir                     break;
182*cdf0e10cSrcweir                 case sal_Unicode('i'):
183*cdf0e10cSrcweir                 case sal_Unicode('I'):
184*cdf0e10cSrcweir                     aCmpsL[0] = "in";
185*cdf0e10cSrcweir                     aCmpsU[0] = "IN";
186*cdf0e10cSrcweir                     aScales[0] = 1000.*2.54; // mm/100
187*cdf0e10cSrcweir                     break;
188*cdf0e10cSrcweir                 case sal_Unicode('m'):
189*cdf0e10cSrcweir                 case sal_Unicode('M'):
190*cdf0e10cSrcweir                     aCmpsL[0] = "mm";
191*cdf0e10cSrcweir                     aCmpsU[0] = "MM";
192*cdf0e10cSrcweir                     aScales[0] = 1.0 * nScaleFactor; // mm/100
193*cdf0e10cSrcweir                     break;
194*cdf0e10cSrcweir                 case sal_Unicode('p'):
195*cdf0e10cSrcweir                 case sal_Unicode('P'):
196*cdf0e10cSrcweir                     aCmpsL[0] = "pt";
197*cdf0e10cSrcweir                     aCmpsU[0] = "PT";
198*cdf0e10cSrcweir                     aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
199*cdf0e10cSrcweir 
200*cdf0e10cSrcweir                     aCmpsL[1] = "pc";
201*cdf0e10cSrcweir                     aCmpsU[1] = "PC";
202*cdf0e10cSrcweir                     aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
203*cdf0e10cSrcweir                     break;
204*cdf0e10cSrcweir                 }
205*cdf0e10cSrcweir             }
206*cdf0e10cSrcweir             else if( MeasureUnit::POINT == nTargetUnit )
207*cdf0e10cSrcweir             {
208*cdf0e10cSrcweir                 if( rString[nPos] == 'p' || rString[nPos] == 'P' )
209*cdf0e10cSrcweir                 {
210*cdf0e10cSrcweir                     aCmpsL[0] = "pt";
211*cdf0e10cSrcweir                     aCmpsU[0] = "PT";
212*cdf0e10cSrcweir                     aScales[0] = 1;
213*cdf0e10cSrcweir                 }
214*cdf0e10cSrcweir             }
215*cdf0e10cSrcweir 
216*cdf0e10cSrcweir             if( aCmpsL[0] == NULL )
217*cdf0e10cSrcweir                 return false;
218*cdf0e10cSrcweir 
219*cdf0e10cSrcweir             double nScale = 0.;
220*cdf0e10cSrcweir             for( sal_uInt16 i= 0; i < 2; i++ )
221*cdf0e10cSrcweir             {
222*cdf0e10cSrcweir                 const sal_Char *pL = aCmpsL[i];
223*cdf0e10cSrcweir                 if( pL )
224*cdf0e10cSrcweir                 {
225*cdf0e10cSrcweir                     const sal_Char *pU = aCmpsU[i];
226*cdf0e10cSrcweir                     while( nPos < nLen && *pL )
227*cdf0e10cSrcweir                     {
228*cdf0e10cSrcweir                         sal_Unicode c = rString[nPos];
229*cdf0e10cSrcweir                         if( c != *pL && c != *pU )
230*cdf0e10cSrcweir                             break;
231*cdf0e10cSrcweir                         pL++;
232*cdf0e10cSrcweir                         pU++;
233*cdf0e10cSrcweir                         nPos++;
234*cdf0e10cSrcweir                     }
235*cdf0e10cSrcweir                     if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
236*cdf0e10cSrcweir                     {
237*cdf0e10cSrcweir                         nScale = aScales[i];
238*cdf0e10cSrcweir                         break;
239*cdf0e10cSrcweir                     }
240*cdf0e10cSrcweir                 }
241*cdf0e10cSrcweir             }
242*cdf0e10cSrcweir 
243*cdf0e10cSrcweir             if( 0. == nScale )
244*cdf0e10cSrcweir                 return false;
245*cdf0e10cSrcweir 
246*cdf0e10cSrcweir             // TODO: check overflow
247*cdf0e10cSrcweir             if( nScale != 1. )
248*cdf0e10cSrcweir                 nVal *= nScale;
249*cdf0e10cSrcweir         }
250*cdf0e10cSrcweir     }
251*cdf0e10cSrcweir 
252*cdf0e10cSrcweir     nVal += .5;
253*cdf0e10cSrcweir     if( bNeg )
254*cdf0e10cSrcweir         nVal = -nVal;
255*cdf0e10cSrcweir 
256*cdf0e10cSrcweir     if( nVal <= (double)nMin )
257*cdf0e10cSrcweir         rValue = nMin;
258*cdf0e10cSrcweir     else if( nVal >= (double)nMax )
259*cdf0e10cSrcweir         rValue = nMax;
260*cdf0e10cSrcweir     else
261*cdf0e10cSrcweir         rValue = (sal_Int32)nVal;
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir     return true;
264*cdf0e10cSrcweir }
265*cdf0e10cSrcweir 
266*cdf0e10cSrcweir /** convert measure in given unit to string with given unit */
267*cdf0e10cSrcweir void Converter::convertMeasure( OUStringBuffer& rBuffer,
268*cdf0e10cSrcweir 								sal_Int32 nMeasure,
269*cdf0e10cSrcweir 								sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
270*cdf0e10cSrcweir 								sal_Int16 nTargetUnit /* = MeasureUnit::INCH */  )
271*cdf0e10cSrcweir {
272*cdf0e10cSrcweir     OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" );
273*cdf0e10cSrcweir     (void)rBuffer;
274*cdf0e10cSrcweir     (void)nMeasure;
275*cdf0e10cSrcweir     (void)nSourceUnit;
276*cdf0e10cSrcweir     (void)nTargetUnit;
277*cdf0e10cSrcweir #if 0
278*cdf0e10cSrcweir     if( nSourceUnit == MeasureUnit::PERCENT )
279*cdf0e10cSrcweir     {
280*cdf0e10cSrcweir         OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
281*cdf0e10cSrcweir                     "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
282*cdf0e10cSrcweir 
283*cdf0e10cSrcweir         rBuffer.append( nMeasure );
284*cdf0e10cSrcweir         rBuffer.append( sal_Unicode('%' ) );
285*cdf0e10cSrcweir     }
286*cdf0e10cSrcweir     else
287*cdf0e10cSrcweir     {
288*cdf0e10cSrcweir 	// the sign is processed seperatly
289*cdf0e10cSrcweir 	if( nMeasure < 0 )
290*cdf0e10cSrcweir 	{
291*cdf0e10cSrcweir 		nMeasure = -nMeasure;
292*cdf0e10cSrcweir 		rBuffer.append( sal_Unicode('-') );
293*cdf0e10cSrcweir 	}
294*cdf0e10cSrcweir 
295*cdf0e10cSrcweir 	// The new length is (nVal * nMul)/(nDiv*nFac*10)
296*cdf0e10cSrcweir 	long nMul = 1000;
297*cdf0e10cSrcweir 	long nDiv = 1;
298*cdf0e10cSrcweir 	long nFac = 100;
299*cdf0e10cSrcweir 	const sal_Char* psUnit = 0;
300*cdf0e10cSrcweir 	switch( nSourceUnit )
301*cdf0e10cSrcweir 	{
302*cdf0e10cSrcweir 	case MeasureUnit::TWIP:
303*cdf0e10cSrcweir 		switch( nTargetUnit )
304*cdf0e10cSrcweir 		{
305*cdf0e10cSrcweir 		case MeasureUnit::MM_100TH:
306*cdf0e10cSrcweir 		case MeasureUnit::MM_10TH:
307*cdf0e10cSrcweir             OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
308*cdf0e10cSrcweir 		case MeasureUnit::MM:
309*cdf0e10cSrcweir 			// 0.01mm = 0.57twip (exactly)
310*cdf0e10cSrcweir 			nMul = 25400;	// 25.4 * 1000
311*cdf0e10cSrcweir 			nDiv = 1440;	// 72 * 20;
312*cdf0e10cSrcweir 			nFac = 100;
313*cdf0e10cSrcweir 			psUnit = gpsMM;
314*cdf0e10cSrcweir 			break;
315*cdf0e10cSrcweir 
316*cdf0e10cSrcweir 		case MeasureUnit::CM:
317*cdf0e10cSrcweir 			// 0.001cm = 0.57twip (exactly)
318*cdf0e10cSrcweir 			nMul = 25400;	// 2.54 * 10000
319*cdf0e10cSrcweir 			nDiv = 1440;	// 72 * 20;
320*cdf0e10cSrcweir 			nFac = 1000;
321*cdf0e10cSrcweir 			psUnit = gpsCM;
322*cdf0e10cSrcweir 			break;
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir 		case MeasureUnit::POINT:
325*cdf0e10cSrcweir 			// 0.01pt = 0.2twip (exactly)
326*cdf0e10cSrcweir 			nMul = 1000;
327*cdf0e10cSrcweir 			nDiv = 20;
328*cdf0e10cSrcweir 			nFac = 100;
329*cdf0e10cSrcweir 			psUnit = gpsPT;
330*cdf0e10cSrcweir 			break;
331*cdf0e10cSrcweir 
332*cdf0e10cSrcweir 		case MeasureUnit::INCH:
333*cdf0e10cSrcweir 		default:
334*cdf0e10cSrcweir             OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
335*cdf0e10cSrcweir 						"output unit not supported for twip values" );
336*cdf0e10cSrcweir 			// 0.0001in = 0.144twip (exactly)
337*cdf0e10cSrcweir 			nMul = 100000;
338*cdf0e10cSrcweir 			nDiv = 1440;	// 72 * 20;
339*cdf0e10cSrcweir 			nFac = 10000;
340*cdf0e10cSrcweir 			psUnit = gpsINCH;
341*cdf0e10cSrcweir 			break;
342*cdf0e10cSrcweir 		}
343*cdf0e10cSrcweir 		break;
344*cdf0e10cSrcweir 
345*cdf0e10cSrcweir 	case MeasureUnit::POINT:
346*cdf0e10cSrcweir 		// 1pt = 1pt (exactly)
347*cdf0e10cSrcweir         OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
348*cdf0e10cSrcweir 					"output unit not supported for pt values" );
349*cdf0e10cSrcweir 		nMul = 10;
350*cdf0e10cSrcweir 		nDiv = 1;
351*cdf0e10cSrcweir 		nFac = 1;
352*cdf0e10cSrcweir 		psUnit = gpsPT;
353*cdf0e10cSrcweir 		break;
354*cdf0e10cSrcweir     case MeasureUnit::MM_10TH:
355*cdf0e10cSrcweir 	case MeasureUnit::MM_100TH:
356*cdf0e10cSrcweir         {
357*cdf0e10cSrcweir             long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
358*cdf0e10cSrcweir 		    switch( nTargetUnit )
359*cdf0e10cSrcweir 		    {
360*cdf0e10cSrcweir 		    case MeasureUnit::MM_100TH:
361*cdf0e10cSrcweir 		    case MeasureUnit::MM_10TH:
362*cdf0e10cSrcweir                 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
363*cdf0e10cSrcweir 						    "output unit not supported for 1/100mm values" );
364*cdf0e10cSrcweir 		    case MeasureUnit::MM:
365*cdf0e10cSrcweir 			    // 0.01mm = 1 mm/100 (exactly)
366*cdf0e10cSrcweir 			    nMul = 10;
367*cdf0e10cSrcweir 			    nDiv = 1;
368*cdf0e10cSrcweir 			    nFac = nFac2;
369*cdf0e10cSrcweir 			    psUnit = gpsMM;
370*cdf0e10cSrcweir 			    break;
371*cdf0e10cSrcweir 
372*cdf0e10cSrcweir 		    case MeasureUnit::CM:
373*cdf0e10cSrcweir 			    // 0.001mm = 1 mm/100 (exactly)
374*cdf0e10cSrcweir 			    nMul = 10;
375*cdf0e10cSrcweir 			    nDiv = 1;	// 72 * 20;
376*cdf0e10cSrcweir 			    nFac = 10*nFac2;
377*cdf0e10cSrcweir 			    psUnit = gpsCM;
378*cdf0e10cSrcweir 			    break;
379*cdf0e10cSrcweir 
380*cdf0e10cSrcweir 		    case MeasureUnit::POINT:
381*cdf0e10cSrcweir 			    // 0.01pt = 0.35 mm/100 (exactly)
382*cdf0e10cSrcweir 			    nMul = 72000;
383*cdf0e10cSrcweir 			    nDiv = 2540;
384*cdf0e10cSrcweir 			    nFac = nFac2;
385*cdf0e10cSrcweir 			    psUnit = gpsPT;
386*cdf0e10cSrcweir 			    break;
387*cdf0e10cSrcweir 
388*cdf0e10cSrcweir 		    case MeasureUnit::INCH:
389*cdf0e10cSrcweir 		    default:
390*cdf0e10cSrcweir                 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
391*cdf0e10cSrcweir 						    "output unit not supported for 1/100mm values" );
392*cdf0e10cSrcweir 			    // 0.0001in = 0.254 mm/100 (exactly)
393*cdf0e10cSrcweir 			    nMul = 100000;
394*cdf0e10cSrcweir 			    nDiv = 2540;
395*cdf0e10cSrcweir 			    nFac = 100*nFac2;
396*cdf0e10cSrcweir 			    psUnit = gpsINCH;
397*cdf0e10cSrcweir 			    break;
398*cdf0e10cSrcweir 		    }
399*cdf0e10cSrcweir 		    break;
400*cdf0e10cSrcweir         }
401*cdf0e10cSrcweir 	}
402*cdf0e10cSrcweir 
403*cdf0e10cSrcweir 	long nLongVal = 0;
404*cdf0e10cSrcweir 	bool bOutLongVal = true;
405*cdf0e10cSrcweir 	if( nMeasure > SAL_INT32_MAX / nMul )
406*cdf0e10cSrcweir 	{
407*cdf0e10cSrcweir 		// A big int is required for calculation
408*cdf0e10cSrcweir 		BigInt nBigVal( nMeasure );
409*cdf0e10cSrcweir 		BigInt nBigFac( nFac );
410*cdf0e10cSrcweir 		nBigVal *= nMul;
411*cdf0e10cSrcweir 		nBigVal /= nDiv;
412*cdf0e10cSrcweir 		nBigVal += 5;
413*cdf0e10cSrcweir 		nBigVal /= 10;
414*cdf0e10cSrcweir 
415*cdf0e10cSrcweir 		if( nBigVal.IsLong() )
416*cdf0e10cSrcweir 		{
417*cdf0e10cSrcweir 			// To convert the value into a string a long is sufficient
418*cdf0e10cSrcweir 			nLongVal = (long)nBigVal;
419*cdf0e10cSrcweir 		}
420*cdf0e10cSrcweir 		else
421*cdf0e10cSrcweir 		{
422*cdf0e10cSrcweir 			BigInt nBigFac2( nFac );
423*cdf0e10cSrcweir 			BigInt nBig10( 10 );
424*cdf0e10cSrcweir 			rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) );
425*cdf0e10cSrcweir 			if( !(nBigVal % nBigFac2).IsZero() )
426*cdf0e10cSrcweir 			{
427*cdf0e10cSrcweir 				rBuffer.append( sal_Unicode('.') );
428*cdf0e10cSrcweir 				while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() )
429*cdf0e10cSrcweir 				{
430*cdf0e10cSrcweir 					nFac /= 10;
431*cdf0e10cSrcweir 					nBigFac2 = nFac;
432*cdf0e10cSrcweir 					rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) );
433*cdf0e10cSrcweir 				}
434*cdf0e10cSrcweir 			}
435*cdf0e10cSrcweir 			bOutLongVal = false;
436*cdf0e10cSrcweir 		}
437*cdf0e10cSrcweir 	}
438*cdf0e10cSrcweir 	else
439*cdf0e10cSrcweir 	{
440*cdf0e10cSrcweir 		nLongVal = nMeasure * nMul;
441*cdf0e10cSrcweir 		nLongVal /= nDiv;
442*cdf0e10cSrcweir 		nLongVal += 5;
443*cdf0e10cSrcweir 		nLongVal /= 10;
444*cdf0e10cSrcweir 	}
445*cdf0e10cSrcweir 
446*cdf0e10cSrcweir 	if( bOutLongVal )
447*cdf0e10cSrcweir 	{
448*cdf0e10cSrcweir 		rBuffer.append( (sal_Int32)(nLongVal / nFac) );
449*cdf0e10cSrcweir 		if( nFac > 1 && (nLongVal % nFac) != 0 )
450*cdf0e10cSrcweir 		{
451*cdf0e10cSrcweir 			rBuffer.append( sal_Unicode('.') );
452*cdf0e10cSrcweir 			while( nFac > 1 && (nLongVal % nFac) != 0 )
453*cdf0e10cSrcweir 			{
454*cdf0e10cSrcweir 				nFac /= 10;
455*cdf0e10cSrcweir 				rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) );
456*cdf0e10cSrcweir 			}
457*cdf0e10cSrcweir 		}
458*cdf0e10cSrcweir 	}
459*cdf0e10cSrcweir 
460*cdf0e10cSrcweir 	if( psUnit )
461*cdf0e10cSrcweir 		rBuffer.appendAscii( psUnit );
462*cdf0e10cSrcweir     }
463*cdf0e10cSrcweir #endif
464*cdf0e10cSrcweir }
465*cdf0e10cSrcweir 
466*cdf0e10cSrcweir static const OUString& getTrueString()
467*cdf0e10cSrcweir {
468*cdf0e10cSrcweir 	static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
469*cdf0e10cSrcweir 	return sTrue;
470*cdf0e10cSrcweir }
471*cdf0e10cSrcweir 
472*cdf0e10cSrcweir static const OUString& getFalseString()
473*cdf0e10cSrcweir {
474*cdf0e10cSrcweir 	static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
475*cdf0e10cSrcweir 	return sFalse;
476*cdf0e10cSrcweir }
477*cdf0e10cSrcweir 
478*cdf0e10cSrcweir /** convert string to boolean */
479*cdf0e10cSrcweir bool Converter::convertBool( bool& rBool, const OUString& rString )
480*cdf0e10cSrcweir {
481*cdf0e10cSrcweir     rBool = rString == getTrueString();
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir     return rBool || (rString == getFalseString());
484*cdf0e10cSrcweir }
485*cdf0e10cSrcweir 
486*cdf0e10cSrcweir /** convert boolean to string */
487*cdf0e10cSrcweir void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
488*cdf0e10cSrcweir {
489*cdf0e10cSrcweir     rBuffer.append( bValue ? getTrueString() : getFalseString() );
490*cdf0e10cSrcweir }
491*cdf0e10cSrcweir 
492*cdf0e10cSrcweir /** convert string to percent */
493*cdf0e10cSrcweir bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString )
494*cdf0e10cSrcweir {
495*cdf0e10cSrcweir     return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
496*cdf0e10cSrcweir }
497*cdf0e10cSrcweir 
498*cdf0e10cSrcweir /** convert percent to string */
499*cdf0e10cSrcweir void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
500*cdf0e10cSrcweir {
501*cdf0e10cSrcweir     rBuffer.append( nValue );
502*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('%' ) );
503*cdf0e10cSrcweir }
504*cdf0e10cSrcweir 
505*cdf0e10cSrcweir /** convert string to pixel measure */
506*cdf0e10cSrcweir bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString )
507*cdf0e10cSrcweir {
508*cdf0e10cSrcweir     return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
509*cdf0e10cSrcweir }
510*cdf0e10cSrcweir 
511*cdf0e10cSrcweir /** convert pixel measure to string */
512*cdf0e10cSrcweir void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
513*cdf0e10cSrcweir {
514*cdf0e10cSrcweir     rBuffer.append( nValue );
515*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('p' ) );
516*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('x' ) );
517*cdf0e10cSrcweir }
518*cdf0e10cSrcweir 
519*cdf0e10cSrcweir int lcl_gethex( int nChar )
520*cdf0e10cSrcweir {
521*cdf0e10cSrcweir     if( nChar >= '0' && nChar <= '9' )
522*cdf0e10cSrcweir         return nChar - '0';
523*cdf0e10cSrcweir     else if( nChar >= 'a' && nChar <= 'f' )
524*cdf0e10cSrcweir         return nChar - 'a' + 10;
525*cdf0e10cSrcweir     else if( nChar >= 'A' && nChar <= 'F' )
526*cdf0e10cSrcweir         return nChar - 'A' + 10;
527*cdf0e10cSrcweir     else
528*cdf0e10cSrcweir         return 0;
529*cdf0e10cSrcweir }
530*cdf0e10cSrcweir 
531*cdf0e10cSrcweir /** convert string to color */
532*cdf0e10cSrcweir bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue )
533*cdf0e10cSrcweir {
534*cdf0e10cSrcweir     if( rValue.getLength() != 7 || rValue[0] != '#' )
535*cdf0e10cSrcweir         return false;
536*cdf0e10cSrcweir 
537*cdf0e10cSrcweir 	rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] );
538*cdf0e10cSrcweir 	rColor <<= 8;
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir 	rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) );
541*cdf0e10cSrcweir 	rColor <<= 8;
542*cdf0e10cSrcweir 
543*cdf0e10cSrcweir 	rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) );
544*cdf0e10cSrcweir 
545*cdf0e10cSrcweir     return true;
546*cdf0e10cSrcweir }
547*cdf0e10cSrcweir 
548*cdf0e10cSrcweir static sal_Char aHexTab[] = "0123456789abcdef";
549*cdf0e10cSrcweir 
550*cdf0e10cSrcweir /** convert color to string */
551*cdf0e10cSrcweir void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
552*cdf0e10cSrcweir {
553*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( '#' ) );
554*cdf0e10cSrcweir 
555*cdf0e10cSrcweir     sal_uInt8 nCol = (sal_uInt8)(nColor >> 16);
556*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
557*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
558*cdf0e10cSrcweir 
559*cdf0e10cSrcweir     nCol = (sal_uInt8)(nColor >> 8);
560*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
561*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
562*cdf0e10cSrcweir 
563*cdf0e10cSrcweir     nCol = (sal_uInt8)nColor;
564*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
565*cdf0e10cSrcweir     rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
566*cdf0e10cSrcweir }
567*cdf0e10cSrcweir 
568*cdf0e10cSrcweir /** convert number to string */
569*cdf0e10cSrcweir void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber )
570*cdf0e10cSrcweir {
571*cdf0e10cSrcweir     rBuffer.append( nNumber );
572*cdf0e10cSrcweir }
573*cdf0e10cSrcweir 
574*cdf0e10cSrcweir /** convert string to number with optional min and max values */
575*cdf0e10cSrcweir bool Converter::convertNumber(	sal_Int32& rValue,
576*cdf0e10cSrcweir 								const OUString& rString,
577*cdf0e10cSrcweir 								sal_Int32 nMin, sal_Int32 nMax )
578*cdf0e10cSrcweir {
579*cdf0e10cSrcweir     bool bNeg = false;
580*cdf0e10cSrcweir     rValue = 0;
581*cdf0e10cSrcweir 
582*cdf0e10cSrcweir     sal_Int32 nPos = 0;
583*cdf0e10cSrcweir     sal_Int32 nLen = rString.getLength();
584*cdf0e10cSrcweir 
585*cdf0e10cSrcweir     // skip white space
586*cdf0e10cSrcweir     while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
587*cdf0e10cSrcweir         nPos++;
588*cdf0e10cSrcweir 
589*cdf0e10cSrcweir     if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
590*cdf0e10cSrcweir     {
591*cdf0e10cSrcweir         bNeg = true;
592*cdf0e10cSrcweir         nPos++;
593*cdf0e10cSrcweir     }
594*cdf0e10cSrcweir 
595*cdf0e10cSrcweir     // get number
596*cdf0e10cSrcweir     while( nPos < nLen &&
597*cdf0e10cSrcweir            sal_Unicode('0') <= rString[nPos] &&
598*cdf0e10cSrcweir            sal_Unicode('9') >= rString[nPos] )
599*cdf0e10cSrcweir     {
600*cdf0e10cSrcweir         // TODO: check overflow!
601*cdf0e10cSrcweir         rValue *= 10;
602*cdf0e10cSrcweir         rValue += (rString[nPos] - sal_Unicode('0'));
603*cdf0e10cSrcweir         nPos++;
604*cdf0e10cSrcweir     }
605*cdf0e10cSrcweir 
606*cdf0e10cSrcweir     if( bNeg )
607*cdf0e10cSrcweir         rValue *= -1;
608*cdf0e10cSrcweir 
609*cdf0e10cSrcweir 	if( rValue < nMin )
610*cdf0e10cSrcweir 		rValue = nMin;
611*cdf0e10cSrcweir 	else if( rValue > nMax )
612*cdf0e10cSrcweir 		rValue = nMax;
613*cdf0e10cSrcweir 
614*cdf0e10cSrcweir     return nPos == nLen;
615*cdf0e10cSrcweir }
616*cdf0e10cSrcweir 
617*cdf0e10cSrcweir /** convert double number to string (using ::rtl::math) */
618*cdf0e10cSrcweir void Converter::convertDouble(  OUStringBuffer& rBuffer,
619*cdf0e10cSrcweir 								double fNumber,
620*cdf0e10cSrcweir 								bool bWriteUnits,
621*cdf0e10cSrcweir 								sal_Int16 nSourceUnit,
622*cdf0e10cSrcweir 								sal_Int16 nTargetUnit)
623*cdf0e10cSrcweir {
624*cdf0e10cSrcweir     if(MeasureUnit::PERCENT == nSourceUnit)
625*cdf0e10cSrcweir     {
626*cdf0e10cSrcweir         OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
627*cdf0e10cSrcweir         ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
628*cdf0e10cSrcweir         if(bWriteUnits)
629*cdf0e10cSrcweir             rBuffer.append(sal_Unicode('%'));
630*cdf0e10cSrcweir     }
631*cdf0e10cSrcweir     else
632*cdf0e10cSrcweir     {
633*cdf0e10cSrcweir         OUStringBuffer sUnit;
634*cdf0e10cSrcweir         double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
635*cdf0e10cSrcweir         if(fFactor != 1.0)
636*cdf0e10cSrcweir             fNumber *= fFactor;
637*cdf0e10cSrcweir         ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
638*cdf0e10cSrcweir         if(bWriteUnits)
639*cdf0e10cSrcweir             rBuffer.append(sUnit);
640*cdf0e10cSrcweir     }
641*cdf0e10cSrcweir }
642*cdf0e10cSrcweir 
643*cdf0e10cSrcweir /** convert double number to string (using ::rtl::math) */
644*cdf0e10cSrcweir void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber)
645*cdf0e10cSrcweir {
646*cdf0e10cSrcweir     ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
647*cdf0e10cSrcweir }
648*cdf0e10cSrcweir 
649*cdf0e10cSrcweir /** convert string to double number (using ::rtl::math) */
650*cdf0e10cSrcweir bool Converter::convertDouble(double& rValue,
651*cdf0e10cSrcweir     const ::rtl::OUString& rString, sal_Int16 nTargetUnit)
652*cdf0e10cSrcweir {
653*cdf0e10cSrcweir 	sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit);
654*cdf0e10cSrcweir 
655*cdf0e10cSrcweir 	return convertDouble(rValue, rString, nSourceUnit, nTargetUnit );
656*cdf0e10cSrcweir }
657*cdf0e10cSrcweir 
658*cdf0e10cSrcweir /** convert string to double number (using ::rtl::math) */
659*cdf0e10cSrcweir bool Converter::convertDouble(double& rValue,
660*cdf0e10cSrcweir     const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
661*cdf0e10cSrcweir {
662*cdf0e10cSrcweir     rtl_math_ConversionStatus eStatus;
663*cdf0e10cSrcweir     rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
664*cdf0e10cSrcweir 
665*cdf0e10cSrcweir     if(eStatus == rtl_math_ConversionStatus_Ok)
666*cdf0e10cSrcweir     {
667*cdf0e10cSrcweir 		OUStringBuffer sUnit;
668*cdf0e10cSrcweir         double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
669*cdf0e10cSrcweir         if(fFactor != 1.0 && fFactor != 0.0)
670*cdf0e10cSrcweir             rValue /= fFactor;
671*cdf0e10cSrcweir     }
672*cdf0e10cSrcweir 
673*cdf0e10cSrcweir     return ( eStatus == rtl_math_ConversionStatus_Ok );
674*cdf0e10cSrcweir }
675*cdf0e10cSrcweir 
676*cdf0e10cSrcweir /** convert string to double number (using ::rtl::math) */
677*cdf0e10cSrcweir bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString)
678*cdf0e10cSrcweir {
679*cdf0e10cSrcweir     rtl_math_ConversionStatus eStatus;
680*cdf0e10cSrcweir     rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
681*cdf0e10cSrcweir     return ( eStatus == rtl_math_ConversionStatus_Ok );
682*cdf0e10cSrcweir }
683*cdf0e10cSrcweir 
684*cdf0e10cSrcweir /** convert double to ISO "duration" string; negative durations allowed */
685*cdf0e10cSrcweir void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
686*cdf0e10cSrcweir                                 const double fTime)
687*cdf0e10cSrcweir {
688*cdf0e10cSrcweir     double fValue = fTime;
689*cdf0e10cSrcweir 
690*cdf0e10cSrcweir     // take care of negative durations as specified in:
691*cdf0e10cSrcweir     // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
692*cdf0e10cSrcweir     if (fValue < 0.0)
693*cdf0e10cSrcweir     {
694*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('-'));
695*cdf0e10cSrcweir         fValue = - fValue;
696*cdf0e10cSrcweir     }
697*cdf0e10cSrcweir 
698*cdf0e10cSrcweir     rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
699*cdf0e10cSrcweir     fValue *= 24;
700*cdf0e10cSrcweir     double fHoursValue = ::rtl::math::approxFloor (fValue);
701*cdf0e10cSrcweir     fValue -= fHoursValue;
702*cdf0e10cSrcweir     fValue *= 60;
703*cdf0e10cSrcweir     double fMinsValue = ::rtl::math::approxFloor (fValue);
704*cdf0e10cSrcweir     fValue -= fMinsValue;
705*cdf0e10cSrcweir     fValue *= 60;
706*cdf0e10cSrcweir     double fSecsValue = ::rtl::math::approxFloor (fValue);
707*cdf0e10cSrcweir     fValue -= fSecsValue;
708*cdf0e10cSrcweir     double f100SecsValue;
709*cdf0e10cSrcweir     if (fValue > 0.00001)
710*cdf0e10cSrcweir         f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
711*cdf0e10cSrcweir     else
712*cdf0e10cSrcweir         f100SecsValue = 0.0;
713*cdf0e10cSrcweir 
714*cdf0e10cSrcweir     if (f100SecsValue == 1.0)
715*cdf0e10cSrcweir     {
716*cdf0e10cSrcweir         f100SecsValue = 0.0;
717*cdf0e10cSrcweir         fSecsValue += 1.0;
718*cdf0e10cSrcweir     }
719*cdf0e10cSrcweir     if (fSecsValue >= 60.0)
720*cdf0e10cSrcweir     {
721*cdf0e10cSrcweir         fSecsValue -= 60.0;
722*cdf0e10cSrcweir         fMinsValue += 1.0;
723*cdf0e10cSrcweir     }
724*cdf0e10cSrcweir     if (fMinsValue >= 60.0)
725*cdf0e10cSrcweir     {
726*cdf0e10cSrcweir         fMinsValue -= 60.0;
727*cdf0e10cSrcweir         fHoursValue += 1.0;
728*cdf0e10cSrcweir     }
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir     if (fHoursValue < 10)
731*cdf0e10cSrcweir         rBuffer.append( sal_Unicode('0'));
732*cdf0e10cSrcweir     rBuffer.append( sal_Int32( fHoursValue));
733*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('H'));
734*cdf0e10cSrcweir     if (fMinsValue < 10)
735*cdf0e10cSrcweir         rBuffer.append( sal_Unicode('0'));
736*cdf0e10cSrcweir     rBuffer.append( sal_Int32( fMinsValue));
737*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('M'));
738*cdf0e10cSrcweir     if (fSecsValue < 10)
739*cdf0e10cSrcweir         rBuffer.append( sal_Unicode('0'));
740*cdf0e10cSrcweir     rBuffer.append( sal_Int32( fSecsValue));
741*cdf0e10cSrcweir     if (f100SecsValue > 0.0)
742*cdf0e10cSrcweir     {
743*cdf0e10cSrcweir         ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
744*cdf0e10cSrcweir                     rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
745*cdf0e10cSrcweir                     true));
746*cdf0e10cSrcweir         if ( a100th.getLength() > 2 )
747*cdf0e10cSrcweir         {
748*cdf0e10cSrcweir             rBuffer.append( sal_Unicode('.'));
749*cdf0e10cSrcweir             rBuffer.append( a100th.copy( 2 ) );     // strip 0.
750*cdf0e10cSrcweir         }
751*cdf0e10cSrcweir     }
752*cdf0e10cSrcweir     rBuffer.append( sal_Unicode('S'));
753*cdf0e10cSrcweir }
754*cdf0e10cSrcweir 
755*cdf0e10cSrcweir /** convert ISO "duration" string to double; negative durations allowed */
756*cdf0e10cSrcweir bool Converter::convertDuration(double& rfTime,
757*cdf0e10cSrcweir                                 const ::rtl::OUString& rString)
758*cdf0e10cSrcweir {
759*cdf0e10cSrcweir     rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
760*cdf0e10cSrcweir     const sal_Unicode* pStr = aTrimmed.getStr();
761*cdf0e10cSrcweir 
762*cdf0e10cSrcweir     // negative time duration?
763*cdf0e10cSrcweir     bool bIsNegativeDuration = false;
764*cdf0e10cSrcweir     if ( sal_Unicode('-') == (*pStr) )
765*cdf0e10cSrcweir     {
766*cdf0e10cSrcweir         bIsNegativeDuration = true;
767*cdf0e10cSrcweir         pStr++;
768*cdf0e10cSrcweir     }
769*cdf0e10cSrcweir 
770*cdf0e10cSrcweir     if ( *(pStr++) != sal_Unicode('P') )            // duration must start with "P"
771*cdf0e10cSrcweir         return false;
772*cdf0e10cSrcweir 
773*cdf0e10cSrcweir     rtl::OUString sDoubleStr;
774*cdf0e10cSrcweir     bool bSuccess = true;
775*cdf0e10cSrcweir     bool bDone = false;
776*cdf0e10cSrcweir     bool bTimePart = false;
777*cdf0e10cSrcweir     bool bIsFraction = false;
778*cdf0e10cSrcweir     sal_Int32 nDays  = 0;
779*cdf0e10cSrcweir     sal_Int32 nHours = 0;
780*cdf0e10cSrcweir     sal_Int32 nMins  = 0;
781*cdf0e10cSrcweir     sal_Int32 nSecs  = 0;
782*cdf0e10cSrcweir     sal_Int32 nTemp = 0;
783*cdf0e10cSrcweir 
784*cdf0e10cSrcweir     while ( bSuccess && !bDone )
785*cdf0e10cSrcweir     {
786*cdf0e10cSrcweir         sal_Unicode c = *(pStr++);
787*cdf0e10cSrcweir         if ( !c )                               // end
788*cdf0e10cSrcweir             bDone = true;
789*cdf0e10cSrcweir         else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
790*cdf0e10cSrcweir         {
791*cdf0e10cSrcweir             if ( nTemp >= SAL_MAX_INT32 / 10 )
792*cdf0e10cSrcweir                 bSuccess = false;
793*cdf0e10cSrcweir             else
794*cdf0e10cSrcweir             {
795*cdf0e10cSrcweir                 if ( !bIsFraction )
796*cdf0e10cSrcweir                 {
797*cdf0e10cSrcweir                     nTemp *= 10;
798*cdf0e10cSrcweir                     nTemp += (c - sal_Unicode('0'));
799*cdf0e10cSrcweir                 }
800*cdf0e10cSrcweir                 else
801*cdf0e10cSrcweir                 {
802*cdf0e10cSrcweir                     sDoubleStr += OUString::valueOf(c);
803*cdf0e10cSrcweir                 }
804*cdf0e10cSrcweir             }
805*cdf0e10cSrcweir         }
806*cdf0e10cSrcweir         else if ( bTimePart )
807*cdf0e10cSrcweir         {
808*cdf0e10cSrcweir             if ( c == sal_Unicode('H') )
809*cdf0e10cSrcweir             {
810*cdf0e10cSrcweir                 nHours = nTemp;
811*cdf0e10cSrcweir                 nTemp = 0;
812*cdf0e10cSrcweir             }
813*cdf0e10cSrcweir             else if ( c == sal_Unicode('M') )
814*cdf0e10cSrcweir             {
815*cdf0e10cSrcweir                 nMins = nTemp;
816*cdf0e10cSrcweir                 nTemp = 0;
817*cdf0e10cSrcweir             }
818*cdf0e10cSrcweir             else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
819*cdf0e10cSrcweir             {
820*cdf0e10cSrcweir                 nSecs = nTemp;
821*cdf0e10cSrcweir                 nTemp = 0;
822*cdf0e10cSrcweir                 bIsFraction = true;
823*cdf0e10cSrcweir                 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
824*cdf0e10cSrcweir             }
825*cdf0e10cSrcweir             else if ( c == sal_Unicode('S') )
826*cdf0e10cSrcweir             {
827*cdf0e10cSrcweir                 if ( !bIsFraction )
828*cdf0e10cSrcweir                 {
829*cdf0e10cSrcweir                     nSecs = nTemp;
830*cdf0e10cSrcweir                     nTemp = 0;
831*cdf0e10cSrcweir                     sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
832*cdf0e10cSrcweir                 }
833*cdf0e10cSrcweir             }
834*cdf0e10cSrcweir             else
835*cdf0e10cSrcweir                 bSuccess = false;               // invalid character
836*cdf0e10cSrcweir         }
837*cdf0e10cSrcweir         else
838*cdf0e10cSrcweir         {
839*cdf0e10cSrcweir             if ( c == sal_Unicode('T') )            // "T" starts time part
840*cdf0e10cSrcweir                 bTimePart = true;
841*cdf0e10cSrcweir             else if ( c == sal_Unicode('D') )
842*cdf0e10cSrcweir             {
843*cdf0e10cSrcweir                 nDays = nTemp;
844*cdf0e10cSrcweir                 nTemp = 0;
845*cdf0e10cSrcweir             }
846*cdf0e10cSrcweir             else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
847*cdf0e10cSrcweir             {
848*cdf0e10cSrcweir                 //! how many days is a year or month?
849*cdf0e10cSrcweir 
850*cdf0e10cSrcweir                 OSL_ENSURE( false, "years or months in duration: not implemented");
851*cdf0e10cSrcweir                 bSuccess = false;
852*cdf0e10cSrcweir             }
853*cdf0e10cSrcweir             else
854*cdf0e10cSrcweir                 bSuccess = false;               // invalid character
855*cdf0e10cSrcweir         }
856*cdf0e10cSrcweir     }
857*cdf0e10cSrcweir 
858*cdf0e10cSrcweir     if ( bSuccess )
859*cdf0e10cSrcweir     {
860*cdf0e10cSrcweir         if ( nDays )
861*cdf0e10cSrcweir             nHours += nDays * 24;               // add the days to the hours part
862*cdf0e10cSrcweir         double fTempTime = 0.0;
863*cdf0e10cSrcweir         double fHour = nHours;
864*cdf0e10cSrcweir         double fMin = nMins;
865*cdf0e10cSrcweir         double fSec = nSecs;
866*cdf0e10cSrcweir         double fSec100 = 0.0;
867*cdf0e10cSrcweir         double fFraction = sDoubleStr.toDouble();
868*cdf0e10cSrcweir         fTempTime = fHour / 24;
869*cdf0e10cSrcweir         fTempTime += fMin / (24 * 60);
870*cdf0e10cSrcweir         fTempTime += fSec / (24 * 60 * 60);
871*cdf0e10cSrcweir         fTempTime += fSec100 / (24 * 60 * 60 * 60);
872*cdf0e10cSrcweir         fTempTime += fFraction / (24 * 60 * 60);
873*cdf0e10cSrcweir 
874*cdf0e10cSrcweir         // negative duration?
875*cdf0e10cSrcweir         if ( bIsNegativeDuration )
876*cdf0e10cSrcweir         {
877*cdf0e10cSrcweir             fTempTime = -fTempTime;
878*cdf0e10cSrcweir         }
879*cdf0e10cSrcweir 
880*cdf0e10cSrcweir         rfTime = fTempTime;
881*cdf0e10cSrcweir     }
882*cdf0e10cSrcweir     return bSuccess;
883*cdf0e10cSrcweir }
884*cdf0e10cSrcweir 
885*cdf0e10cSrcweir /** convert util::Duration to ISO "duration" string */
886*cdf0e10cSrcweir void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
887*cdf0e10cSrcweir         const ::util::Duration& rDuration)
888*cdf0e10cSrcweir {
889*cdf0e10cSrcweir     if (rDuration.Negative)
890*cdf0e10cSrcweir     {
891*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('-'));
892*cdf0e10cSrcweir     }
893*cdf0e10cSrcweir     rBuffer.append(sal_Unicode('P'));
894*cdf0e10cSrcweir     const bool bHaveDate(static_cast<sal_Int32>(rDuration.Years)
895*cdf0e10cSrcweir                         +static_cast<sal_Int32>(rDuration.Months)
896*cdf0e10cSrcweir                         +static_cast<sal_Int32>(rDuration.Days));
897*cdf0e10cSrcweir     if (rDuration.Years)
898*cdf0e10cSrcweir     {
899*cdf0e10cSrcweir         rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
900*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('Y'));
901*cdf0e10cSrcweir     }
902*cdf0e10cSrcweir     if (rDuration.Months)
903*cdf0e10cSrcweir     {
904*cdf0e10cSrcweir         rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
905*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('M'));
906*cdf0e10cSrcweir     }
907*cdf0e10cSrcweir     if (rDuration.Days)
908*cdf0e10cSrcweir     {
909*cdf0e10cSrcweir         rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
910*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('D'));
911*cdf0e10cSrcweir     }
912*cdf0e10cSrcweir     const sal_Int32 nMSecs(static_cast<sal_Int32>(rDuration.Seconds)
913*cdf0e10cSrcweir                          + static_cast<sal_Int32>(rDuration.MilliSeconds));
914*cdf0e10cSrcweir     if (static_cast<sal_Int32>(rDuration.Hours) +
915*cdf0e10cSrcweir         static_cast<sal_Int32>(rDuration.Minutes) + nMSecs)
916*cdf0e10cSrcweir     {
917*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('T')); // time separator
918*cdf0e10cSrcweir         if (rDuration.Hours)
919*cdf0e10cSrcweir         {
920*cdf0e10cSrcweir             rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
921*cdf0e10cSrcweir             rBuffer.append(sal_Unicode('H'));
922*cdf0e10cSrcweir         }
923*cdf0e10cSrcweir         if (rDuration.Minutes)
924*cdf0e10cSrcweir         {
925*cdf0e10cSrcweir             rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
926*cdf0e10cSrcweir             rBuffer.append(sal_Unicode('M'));
927*cdf0e10cSrcweir         }
928*cdf0e10cSrcweir         if (nMSecs)
929*cdf0e10cSrcweir         {
930*cdf0e10cSrcweir             // seconds must not be omitted (i.e. ".42S" is not valid)
931*cdf0e10cSrcweir             rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
932*cdf0e10cSrcweir             if (rDuration.MilliSeconds)
933*cdf0e10cSrcweir             {
934*cdf0e10cSrcweir                 rBuffer.append(sal_Unicode('.'));
935*cdf0e10cSrcweir                 const sal_Int32 nMilliSeconds(rDuration.MilliSeconds % 1000);
936*cdf0e10cSrcweir                 if (nMilliSeconds < 100)
937*cdf0e10cSrcweir                 {
938*cdf0e10cSrcweir                     rBuffer.append(sal_Unicode('0'));
939*cdf0e10cSrcweir                 }
940*cdf0e10cSrcweir                 if (nMilliSeconds < 10)
941*cdf0e10cSrcweir                 {
942*cdf0e10cSrcweir                     rBuffer.append(sal_Unicode('0'));
943*cdf0e10cSrcweir                 }
944*cdf0e10cSrcweir                 if (0 == (nMilliSeconds % 10))
945*cdf0e10cSrcweir                 {
946*cdf0e10cSrcweir                     if (0 == (nMilliSeconds % 100))
947*cdf0e10cSrcweir                     {
948*cdf0e10cSrcweir                         rBuffer.append(nMilliSeconds / 100);
949*cdf0e10cSrcweir                     }
950*cdf0e10cSrcweir                     else
951*cdf0e10cSrcweir                     {
952*cdf0e10cSrcweir                         rBuffer.append(nMilliSeconds / 10);
953*cdf0e10cSrcweir                     }
954*cdf0e10cSrcweir                 }
955*cdf0e10cSrcweir                 else
956*cdf0e10cSrcweir                 {
957*cdf0e10cSrcweir                     rBuffer.append(nMilliSeconds);
958*cdf0e10cSrcweir                 }
959*cdf0e10cSrcweir             }
960*cdf0e10cSrcweir             rBuffer.append(sal_Unicode('S'));
961*cdf0e10cSrcweir         }
962*cdf0e10cSrcweir     }
963*cdf0e10cSrcweir     else if (!bHaveDate)
964*cdf0e10cSrcweir     {
965*cdf0e10cSrcweir         // zero duration: XMLSchema-2 says there must be at least one component
966*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('0'));
967*cdf0e10cSrcweir         rBuffer.append(sal_Unicode('D'));
968*cdf0e10cSrcweir     }
969*cdf0e10cSrcweir }
970*cdf0e10cSrcweir 
971*cdf0e10cSrcweir enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
972*cdf0e10cSrcweir 
973*cdf0e10cSrcweir static Result
974*cdf0e10cSrcweir readUnsignedNumber(const ::rtl::OUString & rString,
975*cdf0e10cSrcweir     sal_Int32 & io_rnPos, sal_Int32 & o_rNumber)
976*cdf0e10cSrcweir {
977*cdf0e10cSrcweir     bool bOverflow(false);
978*cdf0e10cSrcweir     sal_Int32 nTemp(0);
979*cdf0e10cSrcweir     sal_Int32 nPos(io_rnPos);
980*cdf0e10cSrcweir 
981*cdf0e10cSrcweir     while (nPos < rString.getLength())
982*cdf0e10cSrcweir     {
983*cdf0e10cSrcweir         const sal_Unicode c = rString[nPos];
984*cdf0e10cSrcweir         if ((sal_Unicode('0') <= c) && (c <= sal_Unicode('9')))
985*cdf0e10cSrcweir         {
986*cdf0e10cSrcweir             nTemp *= 10;
987*cdf0e10cSrcweir             nTemp += (c - sal_Unicode('0'));
988*cdf0e10cSrcweir             if (nTemp >= SAL_MAX_INT16)
989*cdf0e10cSrcweir             {
990*cdf0e10cSrcweir                 bOverflow = true;
991*cdf0e10cSrcweir             }
992*cdf0e10cSrcweir         }
993*cdf0e10cSrcweir         else
994*cdf0e10cSrcweir         {
995*cdf0e10cSrcweir             break;
996*cdf0e10cSrcweir         }
997*cdf0e10cSrcweir         ++nPos;
998*cdf0e10cSrcweir     }
999*cdf0e10cSrcweir 
1000*cdf0e10cSrcweir     if (io_rnPos == nPos) // read something?
1001*cdf0e10cSrcweir     {
1002*cdf0e10cSrcweir         o_rNumber = -1;
1003*cdf0e10cSrcweir         return R_NOTHING;
1004*cdf0e10cSrcweir     }
1005*cdf0e10cSrcweir 
1006*cdf0e10cSrcweir     io_rnPos = nPos;
1007*cdf0e10cSrcweir     o_rNumber = nTemp;
1008*cdf0e10cSrcweir     return (bOverflow) ? R_OVERFLOW : R_SUCCESS;
1009*cdf0e10cSrcweir }
1010*cdf0e10cSrcweir 
1011*cdf0e10cSrcweir static bool
1012*cdf0e10cSrcweir readDurationT(const ::rtl::OUString & rString, sal_Int32 & io_rnPos)
1013*cdf0e10cSrcweir {
1014*cdf0e10cSrcweir     if ((io_rnPos < rString.getLength()) &&
1015*cdf0e10cSrcweir         (rString[io_rnPos] == sal_Unicode('T')))
1016*cdf0e10cSrcweir     {
1017*cdf0e10cSrcweir         ++io_rnPos;
1018*cdf0e10cSrcweir         return true;
1019*cdf0e10cSrcweir     }
1020*cdf0e10cSrcweir     return false;
1021*cdf0e10cSrcweir }
1022*cdf0e10cSrcweir 
1023*cdf0e10cSrcweir static bool
1024*cdf0e10cSrcweir readDurationComponent(const ::rtl::OUString & rString,
1025*cdf0e10cSrcweir     sal_Int32 & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart,
1026*cdf0e10cSrcweir     sal_Int32 & o_rnTarget, const sal_Unicode c)
1027*cdf0e10cSrcweir {
1028*cdf0e10cSrcweir     if ((io_rnPos < rString.getLength()))
1029*cdf0e10cSrcweir     {
1030*cdf0e10cSrcweir         if (c == rString[io_rnPos])
1031*cdf0e10cSrcweir         {
1032*cdf0e10cSrcweir             ++io_rnPos;
1033*cdf0e10cSrcweir             if (-1 != io_rnTemp)
1034*cdf0e10cSrcweir             {
1035*cdf0e10cSrcweir                 o_rnTarget = io_rnTemp;
1036*cdf0e10cSrcweir                 io_rnTemp = -1;
1037*cdf0e10cSrcweir                 if (!io_rbTimePart)
1038*cdf0e10cSrcweir                 {
1039*cdf0e10cSrcweir                     io_rbTimePart = readDurationT(rString, io_rnPos);
1040*cdf0e10cSrcweir                 }
1041*cdf0e10cSrcweir                 return (R_OVERFLOW !=
1042*cdf0e10cSrcweir                         readUnsignedNumber(rString, io_rnPos, io_rnTemp));
1043*cdf0e10cSrcweir             }
1044*cdf0e10cSrcweir             else
1045*cdf0e10cSrcweir             {
1046*cdf0e10cSrcweir                 return false;
1047*cdf0e10cSrcweir             }
1048*cdf0e10cSrcweir         }
1049*cdf0e10cSrcweir     }
1050*cdf0e10cSrcweir     return true;
1051*cdf0e10cSrcweir }
1052*cdf0e10cSrcweir 
1053*cdf0e10cSrcweir /** convert ISO "duration" string to util::Duration */
1054*cdf0e10cSrcweir bool Converter::convertDuration(util::Duration& rDuration,
1055*cdf0e10cSrcweir                                 const ::rtl::OUString& rString)
1056*cdf0e10cSrcweir {
1057*cdf0e10cSrcweir     const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
1058*cdf0e10cSrcweir     sal_Int32 nPos(0);
1059*cdf0e10cSrcweir 
1060*cdf0e10cSrcweir     bool bIsNegativeDuration(false);
1061*cdf0e10cSrcweir     if (string.getLength() && (sal_Unicode('-') == string[0]))
1062*cdf0e10cSrcweir     {
1063*cdf0e10cSrcweir         bIsNegativeDuration = true;
1064*cdf0e10cSrcweir         ++nPos;
1065*cdf0e10cSrcweir     }
1066*cdf0e10cSrcweir 
1067*cdf0e10cSrcweir     if ((nPos < string.getLength())
1068*cdf0e10cSrcweir         && (string[nPos] != sal_Unicode('P'))) // duration must start with "P"
1069*cdf0e10cSrcweir     {
1070*cdf0e10cSrcweir         return false;
1071*cdf0e10cSrcweir     }
1072*cdf0e10cSrcweir 
1073*cdf0e10cSrcweir     ++nPos;
1074*cdf0e10cSrcweir 
1075*cdf0e10cSrcweir     /// last read number; -1 == no valid number! always reset after using!
1076*cdf0e10cSrcweir     sal_Int32 nTemp(-1);
1077*cdf0e10cSrcweir     bool bTimePart(false); // have we read 'T'?
1078*cdf0e10cSrcweir     bool bSuccess(false);
1079*cdf0e10cSrcweir     sal_Int32 nYears(0);
1080*cdf0e10cSrcweir     sal_Int32 nMonths(0);
1081*cdf0e10cSrcweir     sal_Int32 nDays(0);
1082*cdf0e10cSrcweir     sal_Int32 nHours(0);
1083*cdf0e10cSrcweir     sal_Int32 nMinutes(0);
1084*cdf0e10cSrcweir     sal_Int32 nSeconds(0);
1085*cdf0e10cSrcweir     sal_Int32 nMilliSeconds(0);
1086*cdf0e10cSrcweir 
1087*cdf0e10cSrcweir     bTimePart = readDurationT(string, nPos);
1088*cdf0e10cSrcweir     bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1089*cdf0e10cSrcweir 
1090*cdf0e10cSrcweir     if (!bTimePart && bSuccess)
1091*cdf0e10cSrcweir     {
1092*cdf0e10cSrcweir         bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1093*cdf0e10cSrcweir                      nYears, sal_Unicode('Y'));
1094*cdf0e10cSrcweir     }
1095*cdf0e10cSrcweir 
1096*cdf0e10cSrcweir     if (!bTimePart && bSuccess)
1097*cdf0e10cSrcweir     {
1098*cdf0e10cSrcweir         bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1099*cdf0e10cSrcweir                      nMonths, sal_Unicode('M'));
1100*cdf0e10cSrcweir     }
1101*cdf0e10cSrcweir 
1102*cdf0e10cSrcweir     if (!bTimePart && bSuccess)
1103*cdf0e10cSrcweir     {
1104*cdf0e10cSrcweir         bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1105*cdf0e10cSrcweir                      nDays, sal_Unicode('D'));
1106*cdf0e10cSrcweir     }
1107*cdf0e10cSrcweir 
1108*cdf0e10cSrcweir     if (bTimePart)
1109*cdf0e10cSrcweir     {
1110*cdf0e10cSrcweir         if (-1 == nTemp) // a 'T' must be followed by a component
1111*cdf0e10cSrcweir         {
1112*cdf0e10cSrcweir             bSuccess = false;
1113*cdf0e10cSrcweir         }
1114*cdf0e10cSrcweir 
1115*cdf0e10cSrcweir         if (bSuccess)
1116*cdf0e10cSrcweir         {
1117*cdf0e10cSrcweir             bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1118*cdf0e10cSrcweir                          nHours, sal_Unicode('H'));
1119*cdf0e10cSrcweir         }
1120*cdf0e10cSrcweir 
1121*cdf0e10cSrcweir         if (bSuccess)
1122*cdf0e10cSrcweir         {
1123*cdf0e10cSrcweir             bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1124*cdf0e10cSrcweir                          nMinutes, sal_Unicode('M'));
1125*cdf0e10cSrcweir         }
1126*cdf0e10cSrcweir 
1127*cdf0e10cSrcweir         // eeek! seconds are icky.
1128*cdf0e10cSrcweir         if ((nPos < string.getLength()) && bSuccess)
1129*cdf0e10cSrcweir         {
1130*cdf0e10cSrcweir             if (sal_Unicode('.') == string[nPos])
1131*cdf0e10cSrcweir             {
1132*cdf0e10cSrcweir                 ++nPos;
1133*cdf0e10cSrcweir                 if (-1 != nTemp)
1134*cdf0e10cSrcweir                 {
1135*cdf0e10cSrcweir                     nSeconds = nTemp;
1136*cdf0e10cSrcweir                     nTemp = -1;
1137*cdf0e10cSrcweir                     const sal_Int32 nStart(nPos);
1138*cdf0e10cSrcweir                     bSuccess =
1139*cdf0e10cSrcweir                         (R_NOTHING != readUnsignedNumber(string, nPos, nTemp));
1140*cdf0e10cSrcweir                     if ((nPos < string.getLength()) && bSuccess)
1141*cdf0e10cSrcweir                     {
1142*cdf0e10cSrcweir                         if (-1 != nTemp)
1143*cdf0e10cSrcweir                         {
1144*cdf0e10cSrcweir                             nTemp = -1;
1145*cdf0e10cSrcweir                             const sal_Int32 nDigits = nPos - nStart;
1146*cdf0e10cSrcweir                             OSL_ENSURE(nDigits > 0, "bad code monkey");
1147*cdf0e10cSrcweir                             const sal_Unicode cZero('0');
1148*cdf0e10cSrcweir                             nMilliSeconds = 100 * (string[nStart] - cZero);
1149*cdf0e10cSrcweir                             if (nDigits >= 2)
1150*cdf0e10cSrcweir                             {
1151*cdf0e10cSrcweir                                 nMilliSeconds += 10 *
1152*cdf0e10cSrcweir                                     (string[nStart+1] - cZero);
1153*cdf0e10cSrcweir                                 if (nDigits >= 3)
1154*cdf0e10cSrcweir                                 {
1155*cdf0e10cSrcweir                                     nMilliSeconds += (string[nStart+2] - cZero);
1156*cdf0e10cSrcweir                                 }
1157*cdf0e10cSrcweir                             }
1158*cdf0e10cSrcweir 
1159*cdf0e10cSrcweir                             if (sal_Unicode('S') == string[nPos])
1160*cdf0e10cSrcweir                             {
1161*cdf0e10cSrcweir                                 ++nPos;
1162*cdf0e10cSrcweir                             }
1163*cdf0e10cSrcweir                             else
1164*cdf0e10cSrcweir                             {
1165*cdf0e10cSrcweir                                 bSuccess = false;
1166*cdf0e10cSrcweir                             }
1167*cdf0e10cSrcweir                         }
1168*cdf0e10cSrcweir                         else
1169*cdf0e10cSrcweir                         {
1170*cdf0e10cSrcweir                             bSuccess = false;
1171*cdf0e10cSrcweir                         }
1172*cdf0e10cSrcweir                     }
1173*cdf0e10cSrcweir                 }
1174*cdf0e10cSrcweir                 else
1175*cdf0e10cSrcweir                 {
1176*cdf0e10cSrcweir                     bSuccess = false;
1177*cdf0e10cSrcweir                 }
1178*cdf0e10cSrcweir             }
1179*cdf0e10cSrcweir             else if (sal_Unicode('S') == string[nPos])
1180*cdf0e10cSrcweir             {
1181*cdf0e10cSrcweir                 ++nPos;
1182*cdf0e10cSrcweir                 if (-1 != nTemp)
1183*cdf0e10cSrcweir                 {
1184*cdf0e10cSrcweir                     nSeconds = nTemp;
1185*cdf0e10cSrcweir                     nTemp = -1;
1186*cdf0e10cSrcweir                 }
1187*cdf0e10cSrcweir                 else
1188*cdf0e10cSrcweir                 {
1189*cdf0e10cSrcweir                     bSuccess = false;
1190*cdf0e10cSrcweir                 }
1191*cdf0e10cSrcweir             }
1192*cdf0e10cSrcweir         }
1193*cdf0e10cSrcweir     }
1194*cdf0e10cSrcweir 
1195*cdf0e10cSrcweir     if (nPos != string.getLength()) // string not processed completely?
1196*cdf0e10cSrcweir     {
1197*cdf0e10cSrcweir         bSuccess = false;
1198*cdf0e10cSrcweir     }
1199*cdf0e10cSrcweir 
1200*cdf0e10cSrcweir     if (nTemp != -1) // unprocessed number?
1201*cdf0e10cSrcweir     {
1202*cdf0e10cSrcweir         bSuccess = false;
1203*cdf0e10cSrcweir     }
1204*cdf0e10cSrcweir 
1205*cdf0e10cSrcweir     if (bSuccess)
1206*cdf0e10cSrcweir     {
1207*cdf0e10cSrcweir         rDuration.Negative      = bIsNegativeDuration;
1208*cdf0e10cSrcweir         rDuration.Years         = static_cast<sal_Int16>(nYears);
1209*cdf0e10cSrcweir         rDuration.Months        = static_cast<sal_Int16>(nMonths);
1210*cdf0e10cSrcweir         rDuration.Days          = static_cast<sal_Int16>(nDays);
1211*cdf0e10cSrcweir         rDuration.Hours         = static_cast<sal_Int16>(nHours);
1212*cdf0e10cSrcweir         rDuration.Minutes       = static_cast<sal_Int16>(nMinutes);
1213*cdf0e10cSrcweir         rDuration.Seconds       = static_cast<sal_Int16>(nSeconds);
1214*cdf0e10cSrcweir         rDuration.MilliSeconds  = static_cast<sal_Int16>(nMilliSeconds);
1215*cdf0e10cSrcweir     }
1216*cdf0e10cSrcweir 
1217*cdf0e10cSrcweir     return bSuccess;
1218*cdf0e10cSrcweir }
1219*cdf0e10cSrcweir 
1220*cdf0e10cSrcweir 
1221*cdf0e10cSrcweir /** convert util::Date to ISO "date" string */
1222*cdf0e10cSrcweir void Converter::convertDate(
1223*cdf0e10cSrcweir         ::rtl::OUStringBuffer& i_rBuffer,
1224*cdf0e10cSrcweir         const util::Date& i_rDate)
1225*cdf0e10cSrcweir {
1226*cdf0e10cSrcweir     const util::DateTime dt(
1227*cdf0e10cSrcweir             0, 0, 0, 0, i_rDate.Day, i_rDate.Month, i_rDate.Year);
1228*cdf0e10cSrcweir     convertDateTime(i_rBuffer, dt, false);
1229*cdf0e10cSrcweir }
1230*cdf0e10cSrcweir 
1231*cdf0e10cSrcweir /** convert util::DateTime to ISO "date" or "dateTime" string */
1232*cdf0e10cSrcweir void Converter::convertDateTime(
1233*cdf0e10cSrcweir         ::rtl::OUStringBuffer& i_rBuffer,
1234*cdf0e10cSrcweir         const com::sun::star::util::DateTime& i_rDateTime,
1235*cdf0e10cSrcweir         bool i_bAddTimeIf0AM )
1236*cdf0e10cSrcweir {
1237*cdf0e10cSrcweir     const sal_Unicode dash('-');
1238*cdf0e10cSrcweir     const sal_Unicode col (':');
1239*cdf0e10cSrcweir     const sal_Unicode dot ('.');
1240*cdf0e10cSrcweir     const sal_Unicode zero('0');
1241*cdf0e10cSrcweir     const sal_Unicode tee ('T');
1242*cdf0e10cSrcweir 
1243*cdf0e10cSrcweir     if (i_rDateTime.Year < 1000) {
1244*cdf0e10cSrcweir         i_rBuffer.append(zero);
1245*cdf0e10cSrcweir     }
1246*cdf0e10cSrcweir     if (i_rDateTime.Year < 100) {
1247*cdf0e10cSrcweir         i_rBuffer.append(zero);
1248*cdf0e10cSrcweir     }
1249*cdf0e10cSrcweir     if (i_rDateTime.Year < 10) {
1250*cdf0e10cSrcweir         i_rBuffer.append(zero);
1251*cdf0e10cSrcweir     }
1252*cdf0e10cSrcweir     i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Year)  ).append(dash);
1253*cdf0e10cSrcweir     if( i_rDateTime.Month < 10 ) {
1254*cdf0e10cSrcweir         i_rBuffer.append(zero);
1255*cdf0e10cSrcweir     }
1256*cdf0e10cSrcweir     i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Month) ).append(dash);
1257*cdf0e10cSrcweir     if( i_rDateTime.Day   < 10 ) {
1258*cdf0e10cSrcweir         i_rBuffer.append(zero);
1259*cdf0e10cSrcweir     }
1260*cdf0e10cSrcweir     i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day)   );
1261*cdf0e10cSrcweir 
1262*cdf0e10cSrcweir     if( i_rDateTime.Seconds != 0 ||
1263*cdf0e10cSrcweir         i_rDateTime.Minutes != 0 ||
1264*cdf0e10cSrcweir         i_rDateTime.Hours   != 0 ||
1265*cdf0e10cSrcweir         i_bAddTimeIf0AM )
1266*cdf0e10cSrcweir     {
1267*cdf0e10cSrcweir         i_rBuffer.append(tee);
1268*cdf0e10cSrcweir         if( i_rDateTime.Hours   < 10 ) {
1269*cdf0e10cSrcweir             i_rBuffer.append(zero);
1270*cdf0e10cSrcweir         }
1271*cdf0e10cSrcweir         i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours)   )
1272*cdf0e10cSrcweir                  .append(col);
1273*cdf0e10cSrcweir         if( i_rDateTime.Minutes < 10 ) {
1274*cdf0e10cSrcweir             i_rBuffer.append(zero);
1275*cdf0e10cSrcweir         }
1276*cdf0e10cSrcweir         i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) )
1277*cdf0e10cSrcweir                  .append(col);
1278*cdf0e10cSrcweir         if( i_rDateTime.Seconds < 10 ) {
1279*cdf0e10cSrcweir             i_rBuffer.append(zero);
1280*cdf0e10cSrcweir         }
1281*cdf0e10cSrcweir         i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1282*cdf0e10cSrcweir         if( i_rDateTime.HundredthSeconds > 0 ) {
1283*cdf0e10cSrcweir             i_rBuffer.append(dot);
1284*cdf0e10cSrcweir             if( i_rDateTime.HundredthSeconds < 10 ) {
1285*cdf0e10cSrcweir                 i_rBuffer.append(zero);
1286*cdf0e10cSrcweir             }
1287*cdf0e10cSrcweir             i_rBuffer.append(
1288*cdf0e10cSrcweir                 static_cast<sal_Int32>(i_rDateTime.HundredthSeconds) );
1289*cdf0e10cSrcweir         }
1290*cdf0e10cSrcweir     }
1291*cdf0e10cSrcweir }
1292*cdf0e10cSrcweir 
1293*cdf0e10cSrcweir /** convert ISO "date" or "dateTime" string to util::DateTime */
1294*cdf0e10cSrcweir bool Converter::convertDateTime( util::DateTime& rDateTime,
1295*cdf0e10cSrcweir                                  const ::rtl::OUString& rString )
1296*cdf0e10cSrcweir {
1297*cdf0e10cSrcweir     bool isDateTime;
1298*cdf0e10cSrcweir     util::Date date;
1299*cdf0e10cSrcweir     if (convertDateOrDateTime(date, rDateTime, isDateTime, rString))
1300*cdf0e10cSrcweir     {
1301*cdf0e10cSrcweir         if (!isDateTime)
1302*cdf0e10cSrcweir         {
1303*cdf0e10cSrcweir             rDateTime.Year = date.Year;
1304*cdf0e10cSrcweir             rDateTime.Month = date.Month;
1305*cdf0e10cSrcweir             rDateTime.Day = date.Day;
1306*cdf0e10cSrcweir             rDateTime.Hours = 0;
1307*cdf0e10cSrcweir             rDateTime.Minutes = 0;
1308*cdf0e10cSrcweir             rDateTime.Seconds = 0;
1309*cdf0e10cSrcweir             rDateTime.HundredthSeconds = 0;
1310*cdf0e10cSrcweir         }
1311*cdf0e10cSrcweir         return true;
1312*cdf0e10cSrcweir     }
1313*cdf0e10cSrcweir     else
1314*cdf0e10cSrcweir     {
1315*cdf0e10cSrcweir         return false;
1316*cdf0e10cSrcweir     }
1317*cdf0e10cSrcweir }
1318*cdf0e10cSrcweir 
1319*cdf0e10cSrcweir static bool
1320*cdf0e10cSrcweir readDateTimeComponent(const ::rtl::OUString & rString,
1321*cdf0e10cSrcweir     sal_Int32 & io_rnPos, sal_Int32 & o_rnTarget,
1322*cdf0e10cSrcweir     const sal_Int32 nMinLength, const bool bExactLength)
1323*cdf0e10cSrcweir {
1324*cdf0e10cSrcweir     const sal_Int32 nOldPos(io_rnPos);
1325*cdf0e10cSrcweir     sal_Int32 nTemp(0);
1326*cdf0e10cSrcweir     if (R_SUCCESS != readUnsignedNumber(rString, io_rnPos, nTemp))
1327*cdf0e10cSrcweir     {
1328*cdf0e10cSrcweir         return false;
1329*cdf0e10cSrcweir     }
1330*cdf0e10cSrcweir     const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1331*cdf0e10cSrcweir     if ((nTokenLength < nMinLength) ||
1332*cdf0e10cSrcweir         (bExactLength && (nTokenLength > nMinLength)))
1333*cdf0e10cSrcweir     {
1334*cdf0e10cSrcweir         return false; // bad length
1335*cdf0e10cSrcweir     }
1336*cdf0e10cSrcweir     o_rnTarget = nTemp;
1337*cdf0e10cSrcweir     return true;
1338*cdf0e10cSrcweir }
1339*cdf0e10cSrcweir 
1340*cdf0e10cSrcweir static bool lcl_isLeapYear(const sal_uInt32 nYear)
1341*cdf0e10cSrcweir {
1342*cdf0e10cSrcweir     return ((nYear % 4) == 0)
1343*cdf0e10cSrcweir         && !(((nYear % 100) == 0) || ((nYear % 400) == 0));
1344*cdf0e10cSrcweir }
1345*cdf0e10cSrcweir 
1346*cdf0e10cSrcweir static sal_uInt16
1347*cdf0e10cSrcweir lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear)
1348*cdf0e10cSrcweir {
1349*cdf0e10cSrcweir     static sal_uInt16 s_MaxDaysPerMonth[12] =
1350*cdf0e10cSrcweir         { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1351*cdf0e10cSrcweir     OSL_ASSERT(0 < nMonth && nMonth <= 12);
1352*cdf0e10cSrcweir     if ((2 == nMonth) && lcl_isLeapYear(nYear))
1353*cdf0e10cSrcweir     {
1354*cdf0e10cSrcweir         return 29;
1355*cdf0e10cSrcweir     }
1356*cdf0e10cSrcweir     return s_MaxDaysPerMonth[nMonth - 1];
1357*cdf0e10cSrcweir }
1358*cdf0e10cSrcweir 
1359*cdf0e10cSrcweir /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
1360*cdf0e10cSrcweir bool Converter::convertDateOrDateTime(
1361*cdf0e10cSrcweir                 util::Date & rDate, util::DateTime & rDateTime,
1362*cdf0e10cSrcweir                 bool & rbDateTime, const ::rtl::OUString & rString )
1363*cdf0e10cSrcweir {
1364*cdf0e10cSrcweir     bool bSuccess = true;
1365*cdf0e10cSrcweir 
1366*cdf0e10cSrcweir     const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
1367*cdf0e10cSrcweir     sal_Int32 nPos(0);
1368*cdf0e10cSrcweir     bool bNegative(false);
1369*cdf0e10cSrcweir     if ((string.getLength() > nPos) && (sal_Unicode('-') == string[nPos]))
1370*cdf0e10cSrcweir     {
1371*cdf0e10cSrcweir         ++nPos;
1372*cdf0e10cSrcweir         bNegative = true;
1373*cdf0e10cSrcweir     }
1374*cdf0e10cSrcweir 
1375*cdf0e10cSrcweir     sal_Int32 nYear(0);
1376*cdf0e10cSrcweir     {
1377*cdf0e10cSrcweir         bSuccess = readDateTimeComponent(string, nPos, nYear, 4, false);
1378*cdf0e10cSrcweir         bSuccess &= (0 < nYear);
1379*cdf0e10cSrcweir         bSuccess &= (nPos < string.getLength()); // not last token
1380*cdf0e10cSrcweir     }
1381*cdf0e10cSrcweir     if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
1382*cdf0e10cSrcweir     {
1383*cdf0e10cSrcweir         bSuccess = false;
1384*cdf0e10cSrcweir     }
1385*cdf0e10cSrcweir     if (bSuccess)
1386*cdf0e10cSrcweir     {
1387*cdf0e10cSrcweir         ++nPos;
1388*cdf0e10cSrcweir     }
1389*cdf0e10cSrcweir 
1390*cdf0e10cSrcweir     sal_Int32 nMonth(0);
1391*cdf0e10cSrcweir     if (bSuccess)
1392*cdf0e10cSrcweir     {
1393*cdf0e10cSrcweir         bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true);
1394*cdf0e10cSrcweir         bSuccess &= (0 < nMonth) && (nMonth <= 12);
1395*cdf0e10cSrcweir         bSuccess &= (nPos < string.getLength()); // not last token
1396*cdf0e10cSrcweir     }
1397*cdf0e10cSrcweir     if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
1398*cdf0e10cSrcweir     {
1399*cdf0e10cSrcweir         bSuccess = false;
1400*cdf0e10cSrcweir     }
1401*cdf0e10cSrcweir     if (bSuccess)
1402*cdf0e10cSrcweir     {
1403*cdf0e10cSrcweir         ++nPos;
1404*cdf0e10cSrcweir     }
1405*cdf0e10cSrcweir 
1406*cdf0e10cSrcweir     sal_Int32 nDay(0);
1407*cdf0e10cSrcweir     if (bSuccess)
1408*cdf0e10cSrcweir     {
1409*cdf0e10cSrcweir         bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1410*cdf0e10cSrcweir         bSuccess &= (0 < nDay) && (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear));
1411*cdf0e10cSrcweir     }
1412*cdf0e10cSrcweir 
1413*cdf0e10cSrcweir     bool bHaveTime(false);
1414*cdf0e10cSrcweir     if (bSuccess && (nPos < string.getLength()))
1415*cdf0e10cSrcweir     {
1416*cdf0e10cSrcweir         if (sal_Unicode('T') == string[nPos]) // time separator
1417*cdf0e10cSrcweir         {
1418*cdf0e10cSrcweir             bHaveTime = true;
1419*cdf0e10cSrcweir             ++nPos;
1420*cdf0e10cSrcweir         }
1421*cdf0e10cSrcweir     }
1422*cdf0e10cSrcweir 
1423*cdf0e10cSrcweir     sal_Int32 nHours(0);
1424*cdf0e10cSrcweir     sal_Int32 nMinutes(0);
1425*cdf0e10cSrcweir     sal_Int32 nSeconds(0);
1426*cdf0e10cSrcweir     sal_Int32 nMilliSeconds(0);
1427*cdf0e10cSrcweir     if (bSuccess && bHaveTime)
1428*cdf0e10cSrcweir     {
1429*cdf0e10cSrcweir         {
1430*cdf0e10cSrcweir             bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1431*cdf0e10cSrcweir             bSuccess &= (0 <= nHours) && (nHours <= 24);
1432*cdf0e10cSrcweir             bSuccess &= (nPos < string.getLength()); // not last token
1433*cdf0e10cSrcweir         }
1434*cdf0e10cSrcweir         if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1435*cdf0e10cSrcweir         {
1436*cdf0e10cSrcweir             bSuccess = false;
1437*cdf0e10cSrcweir         }
1438*cdf0e10cSrcweir         if (bSuccess)
1439*cdf0e10cSrcweir         {
1440*cdf0e10cSrcweir             ++nPos;
1441*cdf0e10cSrcweir         }
1442*cdf0e10cSrcweir 
1443*cdf0e10cSrcweir         if (bSuccess)
1444*cdf0e10cSrcweir         {
1445*cdf0e10cSrcweir             bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
1446*cdf0e10cSrcweir             bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
1447*cdf0e10cSrcweir             bSuccess &= (nPos < string.getLength()); // not last token
1448*cdf0e10cSrcweir         }
1449*cdf0e10cSrcweir         if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1450*cdf0e10cSrcweir         {
1451*cdf0e10cSrcweir             bSuccess = false;
1452*cdf0e10cSrcweir         }
1453*cdf0e10cSrcweir         if (bSuccess)
1454*cdf0e10cSrcweir         {
1455*cdf0e10cSrcweir             ++nPos;
1456*cdf0e10cSrcweir         }
1457*cdf0e10cSrcweir 
1458*cdf0e10cSrcweir         if (bSuccess)
1459*cdf0e10cSrcweir         {
1460*cdf0e10cSrcweir             bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
1461*cdf0e10cSrcweir             bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
1462*cdf0e10cSrcweir         }
1463*cdf0e10cSrcweir         if (bSuccess && (nPos < string.getLength()) &&
1464*cdf0e10cSrcweir             (sal_Unicode('.') == string[nPos])) // fraction separator
1465*cdf0e10cSrcweir         {
1466*cdf0e10cSrcweir             ++nPos;
1467*cdf0e10cSrcweir             const sal_Int32 nStart(nPos);
1468*cdf0e10cSrcweir             sal_Int32 nTemp(0);
1469*cdf0e10cSrcweir             if (R_NOTHING == readUnsignedNumber(string, nPos, nTemp))
1470*cdf0e10cSrcweir             {
1471*cdf0e10cSrcweir                 bSuccess = false;
1472*cdf0e10cSrcweir             }
1473*cdf0e10cSrcweir             if (bSuccess)
1474*cdf0e10cSrcweir             {
1475*cdf0e10cSrcweir                 // cannot use nTemp because of possible leading zeros
1476*cdf0e10cSrcweir                 // and possible overflow => read digits directly
1477*cdf0e10cSrcweir                 const sal_Int32 nDigits(nPos - nStart);
1478*cdf0e10cSrcweir                 OSL_ENSURE(nDigits > 0, "bad code monkey");
1479*cdf0e10cSrcweir                 const sal_Unicode cZero('0');
1480*cdf0e10cSrcweir                 nMilliSeconds = 100 * (string[nStart] - cZero);
1481*cdf0e10cSrcweir                 if (nDigits >= 2)
1482*cdf0e10cSrcweir                 {
1483*cdf0e10cSrcweir                     nMilliSeconds += 10 * (string[nStart+1] - cZero);
1484*cdf0e10cSrcweir                     if (nDigits >= 3)
1485*cdf0e10cSrcweir                     {
1486*cdf0e10cSrcweir                         nMilliSeconds += (string[nStart+2] - cZero);
1487*cdf0e10cSrcweir                     }
1488*cdf0e10cSrcweir                 }
1489*cdf0e10cSrcweir             }
1490*cdf0e10cSrcweir         }
1491*cdf0e10cSrcweir 
1492*cdf0e10cSrcweir         if (bSuccess && (nHours == 24))
1493*cdf0e10cSrcweir         {
1494*cdf0e10cSrcweir             if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nMilliSeconds)))
1495*cdf0e10cSrcweir             {
1496*cdf0e10cSrcweir                 bSuccess = false; // only 24:00:00 is valid
1497*cdf0e10cSrcweir             }
1498*cdf0e10cSrcweir #if 0
1499*cdf0e10cSrcweir             else
1500*cdf0e10cSrcweir             {
1501*cdf0e10cSrcweir                 nHours = 0; // normalize 24:00:00 to 00:00:00 of next day
1502*cdf0e10cSrcweir                 lcl_addDay(bNegative, nYear, nMonth, nDay, 1);
1503*cdf0e10cSrcweir             }
1504*cdf0e10cSrcweir #endif
1505*cdf0e10cSrcweir         }
1506*cdf0e10cSrcweir     }
1507*cdf0e10cSrcweir 
1508*cdf0e10cSrcweir     bool bHaveTimezone(false);
1509*cdf0e10cSrcweir     bool bHaveTimezonePlus(false);
1510*cdf0e10cSrcweir     bool bHaveTimezoneMinus(false);
1511*cdf0e10cSrcweir     if (bSuccess && (nPos < string.getLength()))
1512*cdf0e10cSrcweir     {
1513*cdf0e10cSrcweir         const sal_Unicode c(string[nPos]);
1514*cdf0e10cSrcweir         if (sal_Unicode('+') == c)
1515*cdf0e10cSrcweir         {
1516*cdf0e10cSrcweir             bHaveTimezone = true;
1517*cdf0e10cSrcweir             bHaveTimezonePlus = true;
1518*cdf0e10cSrcweir             ++nPos;
1519*cdf0e10cSrcweir         }
1520*cdf0e10cSrcweir         else if (sal_Unicode('-') == c)
1521*cdf0e10cSrcweir         {
1522*cdf0e10cSrcweir             bHaveTimezone = true;
1523*cdf0e10cSrcweir             bHaveTimezoneMinus = true;
1524*cdf0e10cSrcweir             ++nPos;
1525*cdf0e10cSrcweir         }
1526*cdf0e10cSrcweir         else if (sal_Unicode('Z') == c)
1527*cdf0e10cSrcweir         {
1528*cdf0e10cSrcweir             bHaveTimezone = true;
1529*cdf0e10cSrcweir             ++nPos;
1530*cdf0e10cSrcweir         }
1531*cdf0e10cSrcweir         else
1532*cdf0e10cSrcweir         {
1533*cdf0e10cSrcweir             bSuccess = false;
1534*cdf0e10cSrcweir         }
1535*cdf0e10cSrcweir     }
1536*cdf0e10cSrcweir     sal_Int32 nTimezoneHours(0);
1537*cdf0e10cSrcweir     sal_Int32 nTimezoneMinutes(0);
1538*cdf0e10cSrcweir     if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
1539*cdf0e10cSrcweir     {
1540*cdf0e10cSrcweir         bSuccess = readDateTimeComponent(
1541*cdf0e10cSrcweir                         string, nPos, nTimezoneHours, 2, true);
1542*cdf0e10cSrcweir         bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
1543*cdf0e10cSrcweir         bSuccess &= (nPos < string.getLength()); // not last token
1544*cdf0e10cSrcweir         if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1545*cdf0e10cSrcweir         {
1546*cdf0e10cSrcweir             bSuccess = false;
1547*cdf0e10cSrcweir         }
1548*cdf0e10cSrcweir         if (bSuccess)
1549*cdf0e10cSrcweir         {
1550*cdf0e10cSrcweir             ++nPos;
1551*cdf0e10cSrcweir         }
1552*cdf0e10cSrcweir         if (bSuccess)
1553*cdf0e10cSrcweir         {
1554*cdf0e10cSrcweir             bSuccess = readDateTimeComponent(
1555*cdf0e10cSrcweir                         string, nPos, nTimezoneMinutes, 2, true);
1556*cdf0e10cSrcweir             bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
1557*cdf0e10cSrcweir         }
1558*cdf0e10cSrcweir         if (bSuccess && (nTimezoneHours == 14))
1559*cdf0e10cSrcweir         {
1560*cdf0e10cSrcweir             if (0 != nTimezoneMinutes)
1561*cdf0e10cSrcweir             {
1562*cdf0e10cSrcweir                 bSuccess = false; // only +-14:00 is valid
1563*cdf0e10cSrcweir             }
1564*cdf0e10cSrcweir         }
1565*cdf0e10cSrcweir     }
1566*cdf0e10cSrcweir 
1567*cdf0e10cSrcweir     bSuccess &= (nPos == string.getLength()); // trailing junk?
1568*cdf0e10cSrcweir 
1569*cdf0e10cSrcweir     if (bSuccess && bHaveTimezone)
1570*cdf0e10cSrcweir     {
1571*cdf0e10cSrcweir         // util::DateTime does not support timezones!
1572*cdf0e10cSrcweir #if 0
1573*cdf0e10cSrcweir         // do not add timezone, just strip it (as suggested by er)
1574*cdf0e10cSrcweir         lcl_addTimezone(bNegative, nYear, nMonth, nDay, nHours, nMinutes,
1575*cdf0e10cSrcweir                 !bHaveTimezoneMinus, nTimezoneHours, nTimezoneMinutes);
1576*cdf0e10cSrcweir #endif
1577*cdf0e10cSrcweir     }
1578*cdf0e10cSrcweir 
1579*cdf0e10cSrcweir     if (bSuccess)
1580*cdf0e10cSrcweir     {
1581*cdf0e10cSrcweir         if (bHaveTime) // time is optional
1582*cdf0e10cSrcweir         {
1583*cdf0e10cSrcweir             // util::DateTime does not support negative years!
1584*cdf0e10cSrcweir             rDateTime.Year = static_cast<sal_uInt16>(nYear);
1585*cdf0e10cSrcweir             rDateTime.Month = static_cast<sal_uInt16>(nMonth);
1586*cdf0e10cSrcweir             rDateTime.Day = static_cast<sal_uInt16>(nDay);
1587*cdf0e10cSrcweir             rDateTime.Hours = static_cast<sal_uInt16>(nHours);
1588*cdf0e10cSrcweir             rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
1589*cdf0e10cSrcweir             rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
1590*cdf0e10cSrcweir             // util::DateTime does not support 3 decimal digits of precision!
1591*cdf0e10cSrcweir             rDateTime.HundredthSeconds =
1592*cdf0e10cSrcweir                 static_cast<sal_uInt16>(nMilliSeconds / 10);
1593*cdf0e10cSrcweir             rbDateTime = true;
1594*cdf0e10cSrcweir         }
1595*cdf0e10cSrcweir         else
1596*cdf0e10cSrcweir         {
1597*cdf0e10cSrcweir             rDate.Year = static_cast<sal_uInt16>(nYear);
1598*cdf0e10cSrcweir             rDate.Month = static_cast<sal_uInt16>(nMonth);
1599*cdf0e10cSrcweir             rDate.Day = static_cast<sal_uInt16>(nDay);
1600*cdf0e10cSrcweir             rbDateTime = false;
1601*cdf0e10cSrcweir         }
1602*cdf0e10cSrcweir     }
1603*cdf0e10cSrcweir     return bSuccess;
1604*cdf0e10cSrcweir }
1605*cdf0e10cSrcweir 
1606*cdf0e10cSrcweir 
1607*cdf0e10cSrcweir /** gets the position of the first comma after npos in the string
1608*cdf0e10cSrcweir     rStr. Commas inside '"' pairs are not matched */
1609*cdf0e10cSrcweir sal_Int32 Converter::indexOfComma( const OUString& rStr,
1610*cdf0e10cSrcweir                                             sal_Int32 nPos )
1611*cdf0e10cSrcweir {
1612*cdf0e10cSrcweir     sal_Unicode cQuote = 0;
1613*cdf0e10cSrcweir     sal_Int32 nLen = rStr.getLength();
1614*cdf0e10cSrcweir     for( ; nPos < nLen; nPos++ )
1615*cdf0e10cSrcweir     {
1616*cdf0e10cSrcweir         sal_Unicode c = rStr[nPos];
1617*cdf0e10cSrcweir         switch( c )
1618*cdf0e10cSrcweir         {
1619*cdf0e10cSrcweir         case sal_Unicode('\''):
1620*cdf0e10cSrcweir             if( 0 == cQuote )
1621*cdf0e10cSrcweir                 cQuote = c;
1622*cdf0e10cSrcweir             else if( '\'' == cQuote )
1623*cdf0e10cSrcweir                 cQuote = 0;
1624*cdf0e10cSrcweir             break;
1625*cdf0e10cSrcweir 
1626*cdf0e10cSrcweir         case sal_Unicode('"'):
1627*cdf0e10cSrcweir             if( 0 == cQuote )
1628*cdf0e10cSrcweir                 cQuote = c;
1629*cdf0e10cSrcweir             else if( '\"' == cQuote )
1630*cdf0e10cSrcweir                 cQuote = 0;
1631*cdf0e10cSrcweir             break;
1632*cdf0e10cSrcweir 
1633*cdf0e10cSrcweir         case sal_Unicode(','):
1634*cdf0e10cSrcweir             if( 0 == cQuote )
1635*cdf0e10cSrcweir                 return nPos;
1636*cdf0e10cSrcweir             break;
1637*cdf0e10cSrcweir         }
1638*cdf0e10cSrcweir     }
1639*cdf0e10cSrcweir 
1640*cdf0e10cSrcweir     return -1;
1641*cdf0e10cSrcweir }
1642*cdf0e10cSrcweir 
1643*cdf0e10cSrcweir const
1644*cdf0e10cSrcweir   sal_Char aBase64EncodeTable[] =
1645*cdf0e10cSrcweir     { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1646*cdf0e10cSrcweir       'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1647*cdf0e10cSrcweir       'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1648*cdf0e10cSrcweir       'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1649*cdf0e10cSrcweir       '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1650*cdf0e10cSrcweir 
1651*cdf0e10cSrcweir const
1652*cdf0e10cSrcweir   sal_uInt8 aBase64DecodeTable[]  =
1653*cdf0e10cSrcweir     {											 62,255,255,255, 63, // 43-47
1654*cdf0e10cSrcweir //                                                +               /
1655*cdf0e10cSrcweir 
1656*cdf0e10cSrcweir      52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,  0,255,255, // 48-63
1657*cdf0e10cSrcweir //    0   1   2   3   4   5   6   7   8   9               =
1658*cdf0e10cSrcweir 
1659*cdf0e10cSrcweir     255,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, // 64-79
1660*cdf0e10cSrcweir //        A   B   C   D   E   F   G   H   I   J   K   L   M   N   O
1661*cdf0e10cSrcweir 
1662*cdf0e10cSrcweir      15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1663*cdf0e10cSrcweir //    P   Q   R   S   T   U   V   W   X   Y   Z
1664*cdf0e10cSrcweir 
1665*cdf0e10cSrcweir       0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1666*cdf0e10cSrcweir //        a   b   c   d   e   f   g   h   i   j   k   l   m   n   o
1667*cdf0e10cSrcweir 
1668*cdf0e10cSrcweir      41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1669*cdf0e10cSrcweir //    p   q   r   s   t   u   v   w   x   y   z
1670*cdf0e10cSrcweir 
1671*cdf0e10cSrcweir 
1672*cdf0e10cSrcweir 
1673*cdf0e10cSrcweir void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer)
1674*cdf0e10cSrcweir {
1675*cdf0e10cSrcweir     sal_Int32 nLen(nFullLen - nStart);
1676*cdf0e10cSrcweir     if (nLen > 3)
1677*cdf0e10cSrcweir         nLen = 3;
1678*cdf0e10cSrcweir     if (nLen == 0)
1679*cdf0e10cSrcweir     {
1680*cdf0e10cSrcweir         sBuffer.setLength(0);
1681*cdf0e10cSrcweir         return;
1682*cdf0e10cSrcweir     }
1683*cdf0e10cSrcweir 
1684*cdf0e10cSrcweir     sal_Int32 nBinaer;
1685*cdf0e10cSrcweir     switch (nLen)
1686*cdf0e10cSrcweir     {
1687*cdf0e10cSrcweir         case 1:
1688*cdf0e10cSrcweir         {
1689*cdf0e10cSrcweir             nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
1690*cdf0e10cSrcweir         }
1691*cdf0e10cSrcweir         break;
1692*cdf0e10cSrcweir         case 2:
1693*cdf0e10cSrcweir         {
1694*cdf0e10cSrcweir             nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1695*cdf0e10cSrcweir                     (((sal_uInt8)pBuffer[nStart + 1]) <<  8);
1696*cdf0e10cSrcweir         }
1697*cdf0e10cSrcweir         break;
1698*cdf0e10cSrcweir         default:
1699*cdf0e10cSrcweir         {
1700*cdf0e10cSrcweir             nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1701*cdf0e10cSrcweir                     (((sal_uInt8)pBuffer[nStart + 1]) <<  8) +
1702*cdf0e10cSrcweir                     ((sal_uInt8)pBuffer[nStart + 2]);
1703*cdf0e10cSrcweir         }
1704*cdf0e10cSrcweir         break;
1705*cdf0e10cSrcweir     }
1706*cdf0e10cSrcweir 
1707*cdf0e10cSrcweir     sBuffer.appendAscii("====");
1708*cdf0e10cSrcweir 
1709*cdf0e10cSrcweir     sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
1710*cdf0e10cSrcweir     sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]);
1711*cdf0e10cSrcweir 
1712*cdf0e10cSrcweir     nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
1713*cdf0e10cSrcweir     sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]);
1714*cdf0e10cSrcweir     if (nLen == 1)
1715*cdf0e10cSrcweir         return;
1716*cdf0e10cSrcweir 
1717*cdf0e10cSrcweir     nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
1718*cdf0e10cSrcweir     sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]);
1719*cdf0e10cSrcweir     if (nLen == 2)
1720*cdf0e10cSrcweir         return;
1721*cdf0e10cSrcweir 
1722*cdf0e10cSrcweir     nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
1723*cdf0e10cSrcweir     sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]);
1724*cdf0e10cSrcweir }
1725*cdf0e10cSrcweir 
1726*cdf0e10cSrcweir void Converter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
1727*cdf0e10cSrcweir {
1728*cdf0e10cSrcweir 	sal_Int32 i(0);
1729*cdf0e10cSrcweir 	sal_Int32 nBufferLength(aPass.getLength());
1730*cdf0e10cSrcweir 	const sal_Int8* pBuffer = aPass.getConstArray();
1731*cdf0e10cSrcweir 	while (i < nBufferLength)
1732*cdf0e10cSrcweir 	{
1733*cdf0e10cSrcweir 		rtl::OUStringBuffer sBuffer;
1734*cdf0e10cSrcweir 		ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer);
1735*cdf0e10cSrcweir 		aStrBuffer.append(sBuffer);
1736*cdf0e10cSrcweir 		i += 3;
1737*cdf0e10cSrcweir 	}
1738*cdf0e10cSrcweir }
1739*cdf0e10cSrcweir 
1740*cdf0e10cSrcweir void Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer)
1741*cdf0e10cSrcweir {
1742*cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 0
1743*cdf0e10cSrcweir 	sal_Int32 nCharsDecoded =
1744*cdf0e10cSrcweir #endif
1745*cdf0e10cSrcweir 	decodeBase64SomeChars( aBuffer, sBuffer );
1746*cdf0e10cSrcweir 	OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" );
1747*cdf0e10cSrcweir }
1748*cdf0e10cSrcweir 
1749*cdf0e10cSrcweir sal_Int32 Converter::decodeBase64SomeChars(
1750*cdf0e10cSrcweir 		uno::Sequence<sal_Int8>& rOutBuffer,
1751*cdf0e10cSrcweir 		const rtl::OUString& rInBuffer)
1752*cdf0e10cSrcweir {
1753*cdf0e10cSrcweir 	sal_Int32 nInBufferLen = rInBuffer.getLength();
1754*cdf0e10cSrcweir 	sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
1755*cdf0e10cSrcweir 	if( rOutBuffer.getLength() < nMinOutBufferLen )
1756*cdf0e10cSrcweir 		rOutBuffer.realloc( nMinOutBufferLen );
1757*cdf0e10cSrcweir 
1758*cdf0e10cSrcweir 	const sal_Unicode *pInBuffer = rInBuffer.getStr();
1759*cdf0e10cSrcweir 	sal_Int8 *pOutBuffer = rOutBuffer.getArray();
1760*cdf0e10cSrcweir 	sal_Int8 *pOutBufferStart = pOutBuffer;
1761*cdf0e10cSrcweir 	sal_Int32 nCharsDecoded = 0;
1762*cdf0e10cSrcweir 
1763*cdf0e10cSrcweir 	sal_uInt8 aDecodeBuffer[4];
1764*cdf0e10cSrcweir 	sal_Int32 nBytesToDecode = 0;
1765*cdf0e10cSrcweir 	sal_Int32 nBytesGotFromDecoding = 3;
1766*cdf0e10cSrcweir 	sal_Int32 nInBufferPos= 0;
1767*cdf0e10cSrcweir 	while( nInBufferPos < nInBufferLen )
1768*cdf0e10cSrcweir 	{
1769*cdf0e10cSrcweir 		sal_Unicode cChar = *pInBuffer;
1770*cdf0e10cSrcweir 		if( cChar >= '+' && cChar <= 'z' )
1771*cdf0e10cSrcweir 		{
1772*cdf0e10cSrcweir 			sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
1773*cdf0e10cSrcweir 			if( nByte != 255 )
1774*cdf0e10cSrcweir 			{
1775*cdf0e10cSrcweir 				// We have found a valid character!
1776*cdf0e10cSrcweir 				aDecodeBuffer[nBytesToDecode++] = nByte;
1777*cdf0e10cSrcweir 
1778*cdf0e10cSrcweir 				// One '=' character at the end means 2 out bytes
1779*cdf0e10cSrcweir 				// Two '=' characters at the end mean 1 out bytes
1780*cdf0e10cSrcweir 				if( '=' == cChar && nBytesToDecode > 2 )
1781*cdf0e10cSrcweir 					nBytesGotFromDecoding--;
1782*cdf0e10cSrcweir 				if( 4 == nBytesToDecode )
1783*cdf0e10cSrcweir 				{
1784*cdf0e10cSrcweir 					// Four characters found, so we may convert now!
1785*cdf0e10cSrcweir 					sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
1786*cdf0e10cSrcweir 									  (aDecodeBuffer[1] << 12) +
1787*cdf0e10cSrcweir 									  (aDecodeBuffer[2] << 6) +
1788*cdf0e10cSrcweir 									   aDecodeBuffer[3];
1789*cdf0e10cSrcweir 
1790*cdf0e10cSrcweir 					*pOutBuffer++  = (sal_Int8)((nOut & 0xff0000) >> 16);
1791*cdf0e10cSrcweir 					if( nBytesGotFromDecoding > 1 )
1792*cdf0e10cSrcweir 						*pOutBuffer++  = (sal_Int8)((nOut & 0xff00) >> 8);
1793*cdf0e10cSrcweir 					if( nBytesGotFromDecoding > 2 )
1794*cdf0e10cSrcweir 						*pOutBuffer++  = (sal_Int8)(nOut & 0xff);
1795*cdf0e10cSrcweir 					nCharsDecoded = nInBufferPos + 1;
1796*cdf0e10cSrcweir 					nBytesToDecode = 0;
1797*cdf0e10cSrcweir 					nBytesGotFromDecoding = 3;
1798*cdf0e10cSrcweir 				}
1799*cdf0e10cSrcweir 			}
1800*cdf0e10cSrcweir 			else
1801*cdf0e10cSrcweir 			{
1802*cdf0e10cSrcweir 				nCharsDecoded++;
1803*cdf0e10cSrcweir 			}
1804*cdf0e10cSrcweir 		}
1805*cdf0e10cSrcweir 		else
1806*cdf0e10cSrcweir 		{
1807*cdf0e10cSrcweir 			nCharsDecoded++;
1808*cdf0e10cSrcweir 		}
1809*cdf0e10cSrcweir 
1810*cdf0e10cSrcweir 		nInBufferPos++;
1811*cdf0e10cSrcweir 		pInBuffer++;
1812*cdf0e10cSrcweir 	}
1813*cdf0e10cSrcweir 	if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
1814*cdf0e10cSrcweir 		rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
1815*cdf0e10cSrcweir 
1816*cdf0e10cSrcweir 	return nCharsDecoded;
1817*cdf0e10cSrcweir }
1818*cdf0e10cSrcweir 
1819*cdf0e10cSrcweir void Converter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource)
1820*cdf0e10cSrcweir {
1821*cdf0e10cSrcweir 	sal_uInt32 nLength(rSource.getLength());
1822*cdf0e10cSrcweir 	rtl::OUStringBuffer sBuffer(nLength);
1823*cdf0e10cSrcweir 	for (sal_uInt32 i = 0; i < nLength; i++)
1824*cdf0e10cSrcweir 	{
1825*cdf0e10cSrcweir 		sal_Unicode cChar = rSource[i];
1826*cdf0e10cSrcweir 		if (!(cChar < 0x0020) ||
1827*cdf0e10cSrcweir 			(cChar == 0x0009) ||		// TAB
1828*cdf0e10cSrcweir 			(cChar == 0x000A) ||		// LF
1829*cdf0e10cSrcweir 			(cChar == 0x000D))			// legal character
1830*cdf0e10cSrcweir 			sBuffer.append(cChar);
1831*cdf0e10cSrcweir 	}
1832*cdf0e10cSrcweir 	rTarget = sBuffer.makeStringAndClear();
1833*cdf0e10cSrcweir }
1834*cdf0e10cSrcweir 
1835*cdf0e10cSrcweir double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
1836*cdf0e10cSrcweir {
1837*cdf0e10cSrcweir 	double fRetval(1.0);
1838*cdf0e10cSrcweir 	rUnit.setLength(0L);
1839*cdf0e10cSrcweir 
1840*cdf0e10cSrcweir 	const sal_Char* psUnit = 0;
1841*cdf0e10cSrcweir 
1842*cdf0e10cSrcweir 	if(nSourceUnit != nTargetUnit)
1843*cdf0e10cSrcweir 	{
1844*cdf0e10cSrcweir 		switch(nSourceUnit)
1845*cdf0e10cSrcweir 		{
1846*cdf0e10cSrcweir 			case MeasureUnit::TWIP:
1847*cdf0e10cSrcweir 			{
1848*cdf0e10cSrcweir 				switch(nTargetUnit)
1849*cdf0e10cSrcweir 				{
1850*cdf0e10cSrcweir 					case MeasureUnit::MM_100TH:
1851*cdf0e10cSrcweir 					case MeasureUnit::MM_10TH:
1852*cdf0e10cSrcweir 					{
1853*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1854*cdf0e10cSrcweir 					}
1855*cdf0e10cSrcweir 					case MeasureUnit::MM:
1856*cdf0e10cSrcweir 					{
1857*cdf0e10cSrcweir 						// 0.01mm = 0.57twip (exactly)
1858*cdf0e10cSrcweir 						fRetval = ((25400.0 / 1440.0) / 1000.0);
1859*cdf0e10cSrcweir 						psUnit = gpsMM;
1860*cdf0e10cSrcweir 						break;
1861*cdf0e10cSrcweir 					}
1862*cdf0e10cSrcweir 					case MeasureUnit::CM:
1863*cdf0e10cSrcweir 					{
1864*cdf0e10cSrcweir 						// 0.001cm = 0.57twip (exactly)
1865*cdf0e10cSrcweir 						fRetval = ((25400.0 / 1440.0) / 10000.0);
1866*cdf0e10cSrcweir 						psUnit = gpsCM;
1867*cdf0e10cSrcweir 						break;
1868*cdf0e10cSrcweir 					}
1869*cdf0e10cSrcweir 					case MeasureUnit::POINT:
1870*cdf0e10cSrcweir 					{
1871*cdf0e10cSrcweir 						// 0.01pt = 0.2twip (exactly)
1872*cdf0e10cSrcweir 						fRetval = ((1000.0 / 20.0) / 1000.0);
1873*cdf0e10cSrcweir 						psUnit = gpsPT;
1874*cdf0e10cSrcweir 						break;
1875*cdf0e10cSrcweir 					}
1876*cdf0e10cSrcweir 					case MeasureUnit::INCH:
1877*cdf0e10cSrcweir 					default:
1878*cdf0e10cSrcweir 					{
1879*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1880*cdf0e10cSrcweir 						// 0.0001in = 0.144twip (exactly)
1881*cdf0e10cSrcweir 						fRetval = ((100000.0 / 1440.0) / 100000.0);
1882*cdf0e10cSrcweir 						psUnit = gpsINCH;
1883*cdf0e10cSrcweir 						break;
1884*cdf0e10cSrcweir 					}
1885*cdf0e10cSrcweir 				}
1886*cdf0e10cSrcweir 				break;
1887*cdf0e10cSrcweir 			}
1888*cdf0e10cSrcweir 			case MeasureUnit::POINT:
1889*cdf0e10cSrcweir 			{
1890*cdf0e10cSrcweir                 switch(nTargetUnit)
1891*cdf0e10cSrcweir                 {
1892*cdf0e10cSrcweir                     case MeasureUnit::MM:
1893*cdf0e10cSrcweir                         // 1mm = 72 / 25.4 pt (exactly)
1894*cdf0e10cSrcweir                         fRetval = ( 25.4 / 72.0 );
1895*cdf0e10cSrcweir                         psUnit = gpsMM;
1896*cdf0e10cSrcweir                         break;
1897*cdf0e10cSrcweir 
1898*cdf0e10cSrcweir                     case MeasureUnit::CM:
1899*cdf0e10cSrcweir                         // 1cm = 72 / 2.54 pt (exactly)
1900*cdf0e10cSrcweir                         fRetval = ( 2.54 / 72.0 );
1901*cdf0e10cSrcweir                         psUnit = gpsCM;
1902*cdf0e10cSrcweir                         break;
1903*cdf0e10cSrcweir 
1904*cdf0e10cSrcweir                     case MeasureUnit::TWIP:
1905*cdf0e10cSrcweir                         // 1twip = 72 / 1440 pt (exactly)
1906*cdf0e10cSrcweir                         fRetval = 20.0;     // 1440.0 / 72.0
1907*cdf0e10cSrcweir                         psUnit = gpsPC;
1908*cdf0e10cSrcweir                         break;
1909*cdf0e10cSrcweir 
1910*cdf0e10cSrcweir                     case MeasureUnit::INCH:
1911*cdf0e10cSrcweir                     default:
1912*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values");
1913*cdf0e10cSrcweir                         // 1in = 72 pt (exactly)
1914*cdf0e10cSrcweir                         fRetval = ( 1.0 / 72.0 );
1915*cdf0e10cSrcweir                         psUnit = gpsINCH;
1916*cdf0e10cSrcweir                         break;
1917*cdf0e10cSrcweir                 }
1918*cdf0e10cSrcweir                 break;
1919*cdf0e10cSrcweir 			}
1920*cdf0e10cSrcweir             case MeasureUnit::MM_10TH:
1921*cdf0e10cSrcweir 			{
1922*cdf0e10cSrcweir 				switch(nTargetUnit)
1923*cdf0e10cSrcweir 				{
1924*cdf0e10cSrcweir 					case MeasureUnit::MM_100TH:
1925*cdf0e10cSrcweir 					case MeasureUnit::MM_10TH:
1926*cdf0e10cSrcweir 					{
1927*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1928*cdf0e10cSrcweir 					}
1929*cdf0e10cSrcweir 					case MeasureUnit::MM:
1930*cdf0e10cSrcweir 					{
1931*cdf0e10cSrcweir 						// 0.01mm = 1 mm/100 (exactly)
1932*cdf0e10cSrcweir 						fRetval = ((10.0 / 1.0) / 100.0);
1933*cdf0e10cSrcweir 						psUnit = gpsMM;
1934*cdf0e10cSrcweir 						break;
1935*cdf0e10cSrcweir 					}
1936*cdf0e10cSrcweir 					case MeasureUnit::CM:
1937*cdf0e10cSrcweir 					{
1938*cdf0e10cSrcweir 						// 0.001mm = 1 mm/100 (exactly)
1939*cdf0e10cSrcweir 						fRetval = ((10.0 / 1.0) / 1000.0);
1940*cdf0e10cSrcweir 						psUnit = gpsCM;
1941*cdf0e10cSrcweir 						break;
1942*cdf0e10cSrcweir 					}
1943*cdf0e10cSrcweir 					case MeasureUnit::POINT:
1944*cdf0e10cSrcweir 					{
1945*cdf0e10cSrcweir 						// 0.01pt = 0.35 mm/100 (exactly)
1946*cdf0e10cSrcweir 						fRetval = ((72000.0 / 2540.0) / 100.0);
1947*cdf0e10cSrcweir 						psUnit = gpsPT;
1948*cdf0e10cSrcweir 						break;
1949*cdf0e10cSrcweir 					}
1950*cdf0e10cSrcweir 					case MeasureUnit::INCH:
1951*cdf0e10cSrcweir 					default:
1952*cdf0e10cSrcweir 					{
1953*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1954*cdf0e10cSrcweir 						// 0.0001in = 0.254 mm/100 (exactly)
1955*cdf0e10cSrcweir 						fRetval = ((100000.0 / 2540.0) / 10000.0);
1956*cdf0e10cSrcweir 						psUnit = gpsINCH;
1957*cdf0e10cSrcweir 						break;
1958*cdf0e10cSrcweir 					}
1959*cdf0e10cSrcweir 				}
1960*cdf0e10cSrcweir 				break;
1961*cdf0e10cSrcweir             }
1962*cdf0e10cSrcweir 			case MeasureUnit::MM_100TH:
1963*cdf0e10cSrcweir 			{
1964*cdf0e10cSrcweir 				switch(nTargetUnit)
1965*cdf0e10cSrcweir 				{
1966*cdf0e10cSrcweir 					case MeasureUnit::MM_100TH:
1967*cdf0e10cSrcweir 					case MeasureUnit::MM_10TH:
1968*cdf0e10cSrcweir 					{
1969*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1970*cdf0e10cSrcweir 					}
1971*cdf0e10cSrcweir 					case MeasureUnit::MM:
1972*cdf0e10cSrcweir 					{
1973*cdf0e10cSrcweir 						// 0.01mm = 1 mm/100 (exactly)
1974*cdf0e10cSrcweir 						fRetval = ((10.0 / 1.0) / 1000.0);
1975*cdf0e10cSrcweir 						psUnit = gpsMM;
1976*cdf0e10cSrcweir 						break;
1977*cdf0e10cSrcweir 					}
1978*cdf0e10cSrcweir 					case MeasureUnit::CM:
1979*cdf0e10cSrcweir 					{
1980*cdf0e10cSrcweir 						// 0.001mm = 1 mm/100 (exactly)
1981*cdf0e10cSrcweir 						fRetval = ((10.0 / 1.0) / 10000.0);
1982*cdf0e10cSrcweir 						psUnit = gpsCM;
1983*cdf0e10cSrcweir 						break;
1984*cdf0e10cSrcweir 					}
1985*cdf0e10cSrcweir 					case MeasureUnit::POINT:
1986*cdf0e10cSrcweir 					{
1987*cdf0e10cSrcweir 						// 0.01pt = 0.35 mm/100 (exactly)
1988*cdf0e10cSrcweir 						fRetval = ((72000.0 / 2540.0) / 1000.0);
1989*cdf0e10cSrcweir 						psUnit = gpsPT;
1990*cdf0e10cSrcweir 						break;
1991*cdf0e10cSrcweir 					}
1992*cdf0e10cSrcweir 					case MeasureUnit::INCH:
1993*cdf0e10cSrcweir 					default:
1994*cdf0e10cSrcweir 					{
1995*cdf0e10cSrcweir                         OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1996*cdf0e10cSrcweir 						// 0.0001in = 0.254 mm/100 (exactly)
1997*cdf0e10cSrcweir 						fRetval = ((100000.0 / 2540.0) / 100000.0);
1998*cdf0e10cSrcweir 						psUnit = gpsINCH;
1999*cdf0e10cSrcweir 						break;
2000*cdf0e10cSrcweir 					}
2001*cdf0e10cSrcweir 				}
2002*cdf0e10cSrcweir 				break;
2003*cdf0e10cSrcweir 			}
2004*cdf0e10cSrcweir 		}
2005*cdf0e10cSrcweir 
2006*cdf0e10cSrcweir 		if( psUnit )
2007*cdf0e10cSrcweir 			rUnit.appendAscii( psUnit );
2008*cdf0e10cSrcweir 	}
2009*cdf0e10cSrcweir 
2010*cdf0e10cSrcweir 	return fRetval;
2011*cdf0e10cSrcweir }
2012*cdf0e10cSrcweir 
2013*cdf0e10cSrcweir sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit)
2014*cdf0e10cSrcweir {
2015*cdf0e10cSrcweir 	sal_Int32 nPos = 0L;
2016*cdf0e10cSrcweir 	sal_Int32 nLen = rString.getLength();
2017*cdf0e10cSrcweir 	sal_Int16 nRetUnit = nDefaultUnit;
2018*cdf0e10cSrcweir 
2019*cdf0e10cSrcweir 	// skip white space
2020*cdf0e10cSrcweir 	while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
2021*cdf0e10cSrcweir 		nPos++;
2022*cdf0e10cSrcweir 
2023*cdf0e10cSrcweir 	// skip negative
2024*cdf0e10cSrcweir 	if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
2025*cdf0e10cSrcweir 		nPos++;
2026*cdf0e10cSrcweir 
2027*cdf0e10cSrcweir 	// skip number
2028*cdf0e10cSrcweir 	while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
2029*cdf0e10cSrcweir 		nPos++;
2030*cdf0e10cSrcweir 
2031*cdf0e10cSrcweir 	if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
2032*cdf0e10cSrcweir 	{
2033*cdf0e10cSrcweir 		nPos++;
2034*cdf0e10cSrcweir 		while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
2035*cdf0e10cSrcweir 			nPos++;
2036*cdf0e10cSrcweir 	}
2037*cdf0e10cSrcweir 
2038*cdf0e10cSrcweir 	// skip white space
2039*cdf0e10cSrcweir 	while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
2040*cdf0e10cSrcweir 		nPos++;
2041*cdf0e10cSrcweir 
2042*cdf0e10cSrcweir 	if( nPos < nLen )
2043*cdf0e10cSrcweir 	{
2044*cdf0e10cSrcweir 		switch(rString[nPos])
2045*cdf0e10cSrcweir 		{
2046*cdf0e10cSrcweir 			case sal_Unicode('%') :
2047*cdf0e10cSrcweir 			{
2048*cdf0e10cSrcweir 				nRetUnit = MeasureUnit::PERCENT;
2049*cdf0e10cSrcweir 				break;
2050*cdf0e10cSrcweir 			}
2051*cdf0e10cSrcweir 			case sal_Unicode('c'):
2052*cdf0e10cSrcweir 			case sal_Unicode('C'):
2053*cdf0e10cSrcweir 			{
2054*cdf0e10cSrcweir 				if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
2055*cdf0e10cSrcweir 					|| rString[nPos+1] == sal_Unicode('M')))
2056*cdf0e10cSrcweir 					nRetUnit = MeasureUnit::CM;
2057*cdf0e10cSrcweir 				break;
2058*cdf0e10cSrcweir 			}
2059*cdf0e10cSrcweir 			case sal_Unicode('e'):
2060*cdf0e10cSrcweir 			case sal_Unicode('E'):
2061*cdf0e10cSrcweir 			{
2062*cdf0e10cSrcweir 				// CSS1_EMS or CSS1_EMX later
2063*cdf0e10cSrcweir 				break;
2064*cdf0e10cSrcweir 			}
2065*cdf0e10cSrcweir 			case sal_Unicode('i'):
2066*cdf0e10cSrcweir 			case sal_Unicode('I'):
2067*cdf0e10cSrcweir 			{
2068*cdf0e10cSrcweir 				if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n')
2069*cdf0e10cSrcweir 					|| rString[nPos+1] == sal_Unicode('n')))
2070*cdf0e10cSrcweir 					nRetUnit = MeasureUnit::INCH;
2071*cdf0e10cSrcweir 				break;
2072*cdf0e10cSrcweir 			}
2073*cdf0e10cSrcweir 			case sal_Unicode('m'):
2074*cdf0e10cSrcweir 			case sal_Unicode('M'):
2075*cdf0e10cSrcweir 			{
2076*cdf0e10cSrcweir 				if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
2077*cdf0e10cSrcweir 					|| rString[nPos+1] == sal_Unicode('M')))
2078*cdf0e10cSrcweir 					nRetUnit = MeasureUnit::MM;
2079*cdf0e10cSrcweir 				break;
2080*cdf0e10cSrcweir 			}
2081*cdf0e10cSrcweir 			case sal_Unicode('p'):
2082*cdf0e10cSrcweir 			case sal_Unicode('P'):
2083*cdf0e10cSrcweir 			{
2084*cdf0e10cSrcweir 				if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t')
2085*cdf0e10cSrcweir 					|| rString[nPos+1] == sal_Unicode('T')))
2086*cdf0e10cSrcweir 					nRetUnit = MeasureUnit::POINT;
2087*cdf0e10cSrcweir 				if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c')
2088*cdf0e10cSrcweir 					|| rString[nPos+1] == sal_Unicode('C')))
2089*cdf0e10cSrcweir 					nRetUnit = MeasureUnit::TWIP;
2090*cdf0e10cSrcweir 				break;
2091*cdf0e10cSrcweir 			}
2092*cdf0e10cSrcweir 		}
2093*cdf0e10cSrcweir 	}
2094*cdf0e10cSrcweir 
2095*cdf0e10cSrcweir 	return nRetUnit;
2096*cdf0e10cSrcweir }
2097*cdf0e10cSrcweir 
2098*cdf0e10cSrcweir }
2099