140df464eSAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
340df464eSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
440df464eSAndrew Rist * or more contributor license agreements. See the NOTICE file
540df464eSAndrew Rist * distributed with this work for additional information
640df464eSAndrew Rist * regarding copyright ownership. The ASF licenses this file
740df464eSAndrew Rist * to you under the Apache License, Version 2.0 (the
840df464eSAndrew Rist * "License"); you may not use this file except in compliance
940df464eSAndrew Rist * with the License. You may obtain a copy of the License at
1040df464eSAndrew Rist *
1140df464eSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
1240df464eSAndrew Rist *
1340df464eSAndrew Rist * Unless required by applicable law or agreed to in writing,
1440df464eSAndrew Rist * software distributed under the License is distributed on an
1540df464eSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1640df464eSAndrew Rist * KIND, either express or implied. See the License for the
1740df464eSAndrew Rist * specific language governing permissions and limitations
1840df464eSAndrew Rist * under the License.
1940df464eSAndrew Rist *
2040df464eSAndrew Rist *************************************************************/
2140df464eSAndrew Rist
2240df464eSAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_svl.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <ctype.h>
28cdf0e10cSrcweir #include <stdlib.h>
29cdf0e10cSrcweir #include <float.h>
30cdf0e10cSrcweir #include <errno.h>
31cdf0e10cSrcweir #include <tools/date.hxx>
32cdf0e10cSrcweir #include <tools/debug.hxx>
33cdf0e10cSrcweir #include <rtl/math.hxx>
34cdf0e10cSrcweir #include <unotools/charclass.hxx>
35cdf0e10cSrcweir #include <unotools/calendarwrapper.hxx>
36cdf0e10cSrcweir #include <unotools/localedatawrapper.hxx>
37cdf0e10cSrcweir #include <com/sun/star/i18n/CalendarFieldIndex.hpp>
38cdf0e10cSrcweir #include <unotools/digitgroupingiterator.hxx>
39cdf0e10cSrcweir
40cdf0e10cSrcweir #include <svl/zforlist.hxx> // NUMBERFORMAT_XXX
41cdf0e10cSrcweir #include "zforscan.hxx"
42cdf0e10cSrcweir #include <svl/zformat.hxx>
43cdf0e10cSrcweir
44cdf0e10cSrcweir #define _ZFORFIND_CXX
45cdf0e10cSrcweir #include "zforfind.hxx"
46cdf0e10cSrcweir #undef _ZFORFIND_CXX
47cdf0e10cSrcweir
48cdf0e10cSrcweir
49cdf0e10cSrcweir #ifndef DBG_UTIL
50cdf0e10cSrcweir #define NF_TEST_CALENDAR 0
51cdf0e10cSrcweir #else
52cdf0e10cSrcweir #define NF_TEST_CALENDAR 0
53cdf0e10cSrcweir #endif
54cdf0e10cSrcweir #if NF_TEST_CALENDAR
55cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
56cdf0e10cSrcweir #include <com/sun/star/i18n/XExtendedCalendar.hpp>
57cdf0e10cSrcweir #endif
58cdf0e10cSrcweir
59cdf0e10cSrcweir
60cdf0e10cSrcweir const sal_uInt8 ImpSvNumberInputScan::nMatchedEndString = 0x01;
61cdf0e10cSrcweir const sal_uInt8 ImpSvNumberInputScan::nMatchedMidString = 0x02;
62cdf0e10cSrcweir const sal_uInt8 ImpSvNumberInputScan::nMatchedStartString = 0x04;
63cdf0e10cSrcweir const sal_uInt8 ImpSvNumberInputScan::nMatchedVirgin = 0x08;
64cdf0e10cSrcweir const sal_uInt8 ImpSvNumberInputScan::nMatchedUsedAsReturn = 0x10;
65cdf0e10cSrcweir
66cdf0e10cSrcweir /* It is not clear how we want timezones to be handled. Convert them to local
67cdf0e10cSrcweir * time isn't wanted, as it isn't done in any other place and timezone
68cdf0e10cSrcweir * information isn't stored anywhere. Ignoring them and pretending local time
69cdf0e10cSrcweir * may be wrong too and might not be what the user expects. Keep the input as
70cdf0e10cSrcweir * string so that no information is lost.
71cdf0e10cSrcweir * Anyway, defining NF_RECOGNIZE_ISO8601_TIMEZONES to 1 would be the way how it
72cdf0e10cSrcweir * would work, together with the nTimezonePos handling in GetTimeRef(). */
73cdf0e10cSrcweir #define NF_RECOGNIZE_ISO8601_TIMEZONES 0
74cdf0e10cSrcweir
75cdf0e10cSrcweir //---------------------------------------------------------------------------
76cdf0e10cSrcweir // Konstruktor
77cdf0e10cSrcweir
ImpSvNumberInputScan(SvNumberFormatter * pFormatterP)78cdf0e10cSrcweir ImpSvNumberInputScan::ImpSvNumberInputScan( SvNumberFormatter* pFormatterP )
79cdf0e10cSrcweir :
80cdf0e10cSrcweir pUpperMonthText( NULL ),
81cdf0e10cSrcweir pUpperAbbrevMonthText( NULL ),
82cdf0e10cSrcweir pUpperDayText( NULL ),
83cdf0e10cSrcweir pUpperAbbrevDayText( NULL )
84cdf0e10cSrcweir {
85cdf0e10cSrcweir pFormatter = pFormatterP;
86cdf0e10cSrcweir pNullDate = new Date(30,12,1899);
87cdf0e10cSrcweir nYear2000 = SvNumberFormatter::GetYear2000Default();
88cdf0e10cSrcweir Reset();
89cdf0e10cSrcweir ChangeIntl();
90cdf0e10cSrcweir }
91cdf0e10cSrcweir
92cdf0e10cSrcweir
93cdf0e10cSrcweir //---------------------------------------------------------------------------
94cdf0e10cSrcweir // Destruktor
95cdf0e10cSrcweir
~ImpSvNumberInputScan()96cdf0e10cSrcweir ImpSvNumberInputScan::~ImpSvNumberInputScan()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir Reset();
99cdf0e10cSrcweir delete pNullDate;
100cdf0e10cSrcweir delete [] pUpperMonthText;
101cdf0e10cSrcweir delete [] pUpperAbbrevMonthText;
102cdf0e10cSrcweir delete [] pUpperDayText;
103cdf0e10cSrcweir delete [] pUpperAbbrevDayText;
104cdf0e10cSrcweir }
105cdf0e10cSrcweir
106cdf0e10cSrcweir
107cdf0e10cSrcweir //---------------------------------------------------------------------------
108cdf0e10cSrcweir // Reset
109cdf0e10cSrcweir
Reset()110cdf0e10cSrcweir void ImpSvNumberInputScan::Reset()
111cdf0e10cSrcweir {
112cdf0e10cSrcweir #if 0
113cdf0e10cSrcweir // ER 16.06.97 18:56 Vorbelegung erfolgt jetzt in NumberStringDivision,
114cdf0e10cSrcweir // wozu immer alles loeschen wenn einiges wieder benutzt oder gar nicht
115cdf0e10cSrcweir // gebraucht wird..
116cdf0e10cSrcweir for (sal_uInt16 i = 0; i < SV_MAX_ANZ_INPUT_STRINGS; i++)
117cdf0e10cSrcweir {
118cdf0e10cSrcweir sStrArray[i].Erase();
119cdf0e10cSrcweir nNums[i] = SV_MAX_ANZ_INPUT_STRINGS-1;
120cdf0e10cSrcweir IsNum[i] = sal_False;
121cdf0e10cSrcweir }
122cdf0e10cSrcweir #endif
123cdf0e10cSrcweir nMonth = 0;
124cdf0e10cSrcweir nMonthPos = 0;
125cdf0e10cSrcweir nTimePos = 0;
126cdf0e10cSrcweir nSign = 0;
127cdf0e10cSrcweir nESign = 0;
128cdf0e10cSrcweir nDecPos = 0;
129cdf0e10cSrcweir nNegCheck = 0;
130cdf0e10cSrcweir nAnzStrings = 0;
131cdf0e10cSrcweir nAnzNums = 0;
132cdf0e10cSrcweir nThousand = 0;
133cdf0e10cSrcweir eScannedType = NUMBERFORMAT_UNDEFINED;
134cdf0e10cSrcweir nAmPm = 0;
135cdf0e10cSrcweir nPosThousandString = 0;
136cdf0e10cSrcweir nLogical = 0;
137cdf0e10cSrcweir nStringScanNumFor = 0;
138cdf0e10cSrcweir nStringScanSign = 0;
139cdf0e10cSrcweir nMatchedAllStrings = nMatchedVirgin;
140cdf0e10cSrcweir nMayBeIso8601 = 0;
141cdf0e10cSrcweir nTimezonePos = 0;
142cdf0e10cSrcweir }
143cdf0e10cSrcweir
144cdf0e10cSrcweir
145cdf0e10cSrcweir //---------------------------------------------------------------------------
146cdf0e10cSrcweir //
147cdf0e10cSrcweir // static
MyIsdigit(sal_Unicode c)148cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::MyIsdigit( sal_Unicode c )
149cdf0e10cSrcweir {
150cdf0e10cSrcweir // If the input string wouldn't be converted using TransformInput() we'd
151cdf0e10cSrcweir // to use something similar to the following and to adapt many places.
152cdf0e10cSrcweir #if 0
153cdf0e10cSrcweir // use faster isdigit() if possible
154cdf0e10cSrcweir if ( c < 128 )
155cdf0e10cSrcweir return isdigit( (unsigned char) c ) != 0;
156cdf0e10cSrcweir if ( c < 256 )
157cdf0e10cSrcweir return sal_False;
158cdf0e10cSrcweir String aTmp( c );
159cdf0e10cSrcweir return pFormatter->GetCharClass()->isDigit( aTmp, 0 );
160cdf0e10cSrcweir #else
161cdf0e10cSrcweir return c < 128 && isdigit( (unsigned char) c );
162cdf0e10cSrcweir #endif
163cdf0e10cSrcweir }
164cdf0e10cSrcweir
165cdf0e10cSrcweir
166cdf0e10cSrcweir //---------------------------------------------------------------------------
167cdf0e10cSrcweir //
TransformInput(String & rStr)168cdf0e10cSrcweir void ImpSvNumberInputScan::TransformInput( String& rStr )
169cdf0e10cSrcweir {
170cdf0e10cSrcweir xub_StrLen nPos, nLen;
171cdf0e10cSrcweir for ( nPos = 0, nLen = rStr.Len(); nPos < nLen; ++nPos )
172cdf0e10cSrcweir {
173cdf0e10cSrcweir if ( 256 <= rStr.GetChar( nPos ) &&
174cdf0e10cSrcweir pFormatter->GetCharClass()->isDigit( rStr, nPos ) )
175cdf0e10cSrcweir break;
176cdf0e10cSrcweir }
177cdf0e10cSrcweir if ( nPos < nLen )
178cdf0e10cSrcweir rStr = pFormatter->GetNatNum()->getNativeNumberString( rStr,
179cdf0e10cSrcweir pFormatter->GetLocale(), 0 );
180cdf0e10cSrcweir }
181cdf0e10cSrcweir
182cdf0e10cSrcweir
183cdf0e10cSrcweir //---------------------------------------------------------------------------
184cdf0e10cSrcweir // StringToDouble
185cdf0e10cSrcweir //
186cdf0e10cSrcweir // Only simple unsigned floating point values without any error detection,
187cdf0e10cSrcweir // decimal separator has to be '.'
188cdf0e10cSrcweir
StringToDouble(const String & rStr,sal_Bool bForceFraction)189cdf0e10cSrcweir double ImpSvNumberInputScan::StringToDouble( const String& rStr, sal_Bool bForceFraction )
190cdf0e10cSrcweir {
191cdf0e10cSrcweir double fNum = 0.0;
192cdf0e10cSrcweir double fFrac = 0.0;
193cdf0e10cSrcweir int nExp = 0;
194cdf0e10cSrcweir xub_StrLen nPos = 0;
195cdf0e10cSrcweir xub_StrLen nLen = rStr.Len();
196cdf0e10cSrcweir sal_Bool bPreSep = !bForceFraction;
197cdf0e10cSrcweir
198cdf0e10cSrcweir while (nPos < nLen)
199cdf0e10cSrcweir {
200cdf0e10cSrcweir if (rStr.GetChar(nPos) == '.')
201cdf0e10cSrcweir bPreSep = sal_False;
202cdf0e10cSrcweir else if (bPreSep)
203cdf0e10cSrcweir fNum = fNum * 10.0 + (double) (rStr.GetChar(nPos) - '0');
204cdf0e10cSrcweir else
205cdf0e10cSrcweir {
206cdf0e10cSrcweir fFrac = fFrac * 10.0 + (double) (rStr.GetChar(nPos) - '0');
207cdf0e10cSrcweir --nExp;
208cdf0e10cSrcweir }
209cdf0e10cSrcweir nPos++;
210cdf0e10cSrcweir }
211cdf0e10cSrcweir if ( fFrac )
212cdf0e10cSrcweir return fNum + ::rtl::math::pow10Exp( fFrac, nExp );
213cdf0e10cSrcweir return fNum;
214cdf0e10cSrcweir }
215cdf0e10cSrcweir
216cdf0e10cSrcweir
217cdf0e10cSrcweir //---------------------------------------------------------------------------
218cdf0e10cSrcweir // NextNumberStringSymbol
219cdf0e10cSrcweir //
220c71adef7SDamjan Jovanovic // Splits the input into numbers and strings for further processing
221c71adef7SDamjan Jovanovic // (Turing-Machine).
222cdf0e10cSrcweir //---------------------------------------------------------------------------
223c71adef7SDamjan Jovanovic // Initial State = GetChar
224c71adef7SDamjan Jovanovic //---------------+-------------------+-------------------------+-------------
225c71adef7SDamjan Jovanovic // Former State | Read Character | Action | New State
226c71adef7SDamjan Jovanovic //---------------+-------------------+-------------------------+-------------
227c71adef7SDamjan Jovanovic // GetChar | Digit | Symbol=Character | GetValue
228c71adef7SDamjan Jovanovic // | Else | Symbol=Character | GetString
229c71adef7SDamjan Jovanovic //---------------|-------------------+-------------------------+-------------
230c71adef7SDamjan Jovanovic // GetValue | Digit | Symbol=Symbol+Character | GetValue
231c71adef7SDamjan Jovanovic // | Else | Dec(CharPos) | Stop
232c71adef7SDamjan Jovanovic //---------------+-------------------+-------------------------+-------------
233c71adef7SDamjan Jovanovic // GetString | Digit | Dec(CharPos) | Stop
234c71adef7SDamjan Jovanovic // | Else | Symbol=Symbol+Character | GetString
235c71adef7SDamjan Jovanovic //---------------+-------------------+-------------------------+-------------
236c71adef7SDamjan Jovanovic
237c71adef7SDamjan Jovanovic enum ScanState // States of the Turing-Maschine
238cdf0e10cSrcweir {
239cdf0e10cSrcweir SsStop = 0,
240cdf0e10cSrcweir SsStart = 1,
241cdf0e10cSrcweir SsGetValue = 2,
242cdf0e10cSrcweir SsGetString = 3
243cdf0e10cSrcweir };
244cdf0e10cSrcweir
NextNumberStringSymbol(const sal_Unicode * & pStr,String & rSymbol)245cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::NextNumberStringSymbol(
246cdf0e10cSrcweir const sal_Unicode*& pStr,
247cdf0e10cSrcweir String& rSymbol )
248cdf0e10cSrcweir {
249cdf0e10cSrcweir sal_Bool isNumber = sal_False;
250cdf0e10cSrcweir sal_Unicode cToken;
251cdf0e10cSrcweir ScanState eState = SsStart;
252cdf0e10cSrcweir register const sal_Unicode* pHere = pStr;
253cdf0e10cSrcweir register xub_StrLen nChars = 0;
254cdf0e10cSrcweir
255cdf0e10cSrcweir while ( ((cToken = *pHere) != 0) && eState != SsStop)
256cdf0e10cSrcweir {
257cdf0e10cSrcweir pHere++;
258cdf0e10cSrcweir switch (eState)
259cdf0e10cSrcweir {
260cdf0e10cSrcweir case SsStart:
261cdf0e10cSrcweir if ( MyIsdigit( cToken ) )
262cdf0e10cSrcweir {
263cdf0e10cSrcweir eState = SsGetValue;
264cdf0e10cSrcweir isNumber = sal_True;
265cdf0e10cSrcweir }
266cdf0e10cSrcweir else
267cdf0e10cSrcweir eState = SsGetString;
268cdf0e10cSrcweir nChars++;
269cdf0e10cSrcweir break;
270cdf0e10cSrcweir case SsGetValue:
271cdf0e10cSrcweir if ( MyIsdigit( cToken ) )
272cdf0e10cSrcweir nChars++;
273cdf0e10cSrcweir else
274cdf0e10cSrcweir {
275cdf0e10cSrcweir eState = SsStop;
276cdf0e10cSrcweir pHere--;
277cdf0e10cSrcweir }
278cdf0e10cSrcweir break;
279cdf0e10cSrcweir case SsGetString:
280cdf0e10cSrcweir if ( !MyIsdigit( cToken ) )
281cdf0e10cSrcweir nChars++;
282cdf0e10cSrcweir else
283cdf0e10cSrcweir {
284cdf0e10cSrcweir eState = SsStop;
285cdf0e10cSrcweir pHere--;
286cdf0e10cSrcweir }
287cdf0e10cSrcweir break;
288cdf0e10cSrcweir default:
289cdf0e10cSrcweir break;
290cdf0e10cSrcweir } // switch
291cdf0e10cSrcweir } // while
292cdf0e10cSrcweir
293cdf0e10cSrcweir if ( nChars )
294cdf0e10cSrcweir rSymbol.Assign( pStr, nChars );
295cdf0e10cSrcweir else
296cdf0e10cSrcweir rSymbol.Erase();
297cdf0e10cSrcweir
298cdf0e10cSrcweir pStr = pHere;
299cdf0e10cSrcweir
300cdf0e10cSrcweir return isNumber;
301cdf0e10cSrcweir }
302cdf0e10cSrcweir
303cdf0e10cSrcweir
304cdf0e10cSrcweir //---------------------------------------------------------------------------
305cdf0e10cSrcweir // SkipThousands
306cdf0e10cSrcweir
307cdf0e10cSrcweir // FIXME: should be grouping; it is only used though in case nAnzStrings is
308cdf0e10cSrcweir // near SV_MAX_ANZ_INPUT_STRINGS, in NumberStringDivision().
309cdf0e10cSrcweir
SkipThousands(const sal_Unicode * & pStr,String & rSymbol)310cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::SkipThousands(
311cdf0e10cSrcweir const sal_Unicode*& pStr,
312cdf0e10cSrcweir String& rSymbol )
313cdf0e10cSrcweir {
314cdf0e10cSrcweir sal_Bool res = sal_False;
315cdf0e10cSrcweir sal_Unicode cToken;
316cdf0e10cSrcweir const String& rThSep = pFormatter->GetNumThousandSep();
317cdf0e10cSrcweir register const sal_Unicode* pHere = pStr;
318cdf0e10cSrcweir ScanState eState = SsStart;
319cdf0e10cSrcweir xub_StrLen nCounter = 0; // counts 3 digits
320cdf0e10cSrcweir
321cdf0e10cSrcweir while ( ((cToken = *pHere) != 0) && eState != SsStop)
322cdf0e10cSrcweir {
323cdf0e10cSrcweir pHere++;
324cdf0e10cSrcweir switch (eState)
325cdf0e10cSrcweir {
326cdf0e10cSrcweir case SsStart:
327cdf0e10cSrcweir if ( StringPtrContains( rThSep, pHere-1, 0 ) )
328cdf0e10cSrcweir {
329cdf0e10cSrcweir nCounter = 0;
330cdf0e10cSrcweir eState = SsGetValue;
331cdf0e10cSrcweir pHere += rThSep.Len()-1;
332cdf0e10cSrcweir }
333cdf0e10cSrcweir else
334cdf0e10cSrcweir {
335cdf0e10cSrcweir eState = SsStop;
336cdf0e10cSrcweir pHere--;
337cdf0e10cSrcweir }
338cdf0e10cSrcweir break;
339cdf0e10cSrcweir case SsGetValue:
340cdf0e10cSrcweir if ( MyIsdigit( cToken ) )
341cdf0e10cSrcweir {
342cdf0e10cSrcweir rSymbol += cToken;
343cdf0e10cSrcweir nCounter++;
344cdf0e10cSrcweir if (nCounter == 3)
345cdf0e10cSrcweir {
346cdf0e10cSrcweir eState = SsStart;
347cdf0e10cSrcweir res = sal_True; // .000 combination found
348cdf0e10cSrcweir }
349cdf0e10cSrcweir }
350cdf0e10cSrcweir else
351cdf0e10cSrcweir {
352cdf0e10cSrcweir eState = SsStop;
353cdf0e10cSrcweir pHere--;
354cdf0e10cSrcweir }
355cdf0e10cSrcweir break;
356cdf0e10cSrcweir default:
357cdf0e10cSrcweir break;
358cdf0e10cSrcweir } // switch
359cdf0e10cSrcweir } // while
360cdf0e10cSrcweir
361cdf0e10cSrcweir if (eState == SsGetValue) // break witth less than 3 digits
362cdf0e10cSrcweir {
363cdf0e10cSrcweir if ( nCounter )
364cdf0e10cSrcweir rSymbol.Erase( rSymbol.Len() - nCounter, nCounter );
365cdf0e10cSrcweir pHere -= nCounter + rThSep.Len(); // put back ThSep also
366cdf0e10cSrcweir }
367cdf0e10cSrcweir pStr = pHere;
368cdf0e10cSrcweir
369cdf0e10cSrcweir return res;
370cdf0e10cSrcweir }
371cdf0e10cSrcweir
372cdf0e10cSrcweir
373cdf0e10cSrcweir //---------------------------------------------------------------------------
374cdf0e10cSrcweir // NumberStringDivision
375cdf0e10cSrcweir
NumberStringDivision(const String & rString)376cdf0e10cSrcweir void ImpSvNumberInputScan::NumberStringDivision( const String& rString )
377cdf0e10cSrcweir {
378cdf0e10cSrcweir const sal_Unicode* pStr = rString.GetBuffer();
379cdf0e10cSrcweir const sal_Unicode* const pEnd = pStr + rString.Len();
380cdf0e10cSrcweir while ( pStr < pEnd && nAnzStrings < SV_MAX_ANZ_INPUT_STRINGS )
381cdf0e10cSrcweir {
382cdf0e10cSrcweir if ( NextNumberStringSymbol( pStr, sStrArray[nAnzStrings] ) )
383cdf0e10cSrcweir { // Zahl
384cdf0e10cSrcweir IsNum[nAnzStrings] = sal_True;
385cdf0e10cSrcweir nNums[nAnzNums] = nAnzStrings;
386cdf0e10cSrcweir nAnzNums++;
387cdf0e10cSrcweir if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS - 7 &&
388cdf0e10cSrcweir nPosThousandString == 0) // nur einmal
389cdf0e10cSrcweir if ( SkipThousands( pStr, sStrArray[nAnzStrings] ) )
390cdf0e10cSrcweir nPosThousandString = nAnzStrings;
391cdf0e10cSrcweir }
392cdf0e10cSrcweir else
393cdf0e10cSrcweir {
394cdf0e10cSrcweir IsNum[nAnzStrings] = sal_False;
395cdf0e10cSrcweir }
396cdf0e10cSrcweir nAnzStrings++;
397cdf0e10cSrcweir }
398cdf0e10cSrcweir }
399cdf0e10cSrcweir
400cdf0e10cSrcweir
401cdf0e10cSrcweir //---------------------------------------------------------------------------
402cdf0e10cSrcweir // Whether rString contains rWhat at nPos
403cdf0e10cSrcweir
StringContainsImpl(const String & rWhat,const String & rString,xub_StrLen nPos)404cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::StringContainsImpl( const String& rWhat,
405cdf0e10cSrcweir const String& rString, xub_StrLen nPos )
406cdf0e10cSrcweir {
407cdf0e10cSrcweir if ( nPos + rWhat.Len() <= rString.Len() )
408cdf0e10cSrcweir return StringPtrContainsImpl( rWhat, rString.GetBuffer(), nPos );
409cdf0e10cSrcweir return sal_False;
410cdf0e10cSrcweir }
411cdf0e10cSrcweir
412cdf0e10cSrcweir
413cdf0e10cSrcweir //---------------------------------------------------------------------------
414cdf0e10cSrcweir // Whether pString contains rWhat at nPos
415cdf0e10cSrcweir
StringPtrContainsImpl(const String & rWhat,const sal_Unicode * pString,xub_StrLen nPos)416cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::StringPtrContainsImpl( const String& rWhat,
417cdf0e10cSrcweir const sal_Unicode* pString, xub_StrLen nPos )
418cdf0e10cSrcweir {
419cdf0e10cSrcweir if ( rWhat.Len() == 0 )
420cdf0e10cSrcweir return sal_False;
421cdf0e10cSrcweir register const sal_Unicode* pWhat = rWhat.GetBuffer();
422cdf0e10cSrcweir register const sal_Unicode* const pEnd = pWhat + rWhat.Len();
423cdf0e10cSrcweir register const sal_Unicode* pStr = pString + nPos;
424cdf0e10cSrcweir while ( pWhat < pEnd )
425cdf0e10cSrcweir {
426cdf0e10cSrcweir if ( *pWhat != *pStr )
427cdf0e10cSrcweir return sal_False;
428cdf0e10cSrcweir pWhat++;
429cdf0e10cSrcweir pStr++;
430cdf0e10cSrcweir }
431cdf0e10cSrcweir return sal_True;
432cdf0e10cSrcweir }
433cdf0e10cSrcweir
434cdf0e10cSrcweir
435cdf0e10cSrcweir //---------------------------------------------------------------------------
436cdf0e10cSrcweir // SkipChar
437cdf0e10cSrcweir //
438cdf0e10cSrcweir // ueberspringt genau das angegebene Zeichen
439cdf0e10cSrcweir
SkipChar(sal_Unicode c,const String & rString,xub_StrLen & nPos)440cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::SkipChar( sal_Unicode c, const String& rString,
441cdf0e10cSrcweir xub_StrLen& nPos )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir if ((nPos < rString.Len()) && (rString.GetChar(nPos) == c))
444cdf0e10cSrcweir {
445cdf0e10cSrcweir nPos++;
446cdf0e10cSrcweir return sal_True;
447cdf0e10cSrcweir }
448cdf0e10cSrcweir return sal_False;
449cdf0e10cSrcweir }
450cdf0e10cSrcweir
451cdf0e10cSrcweir
452cdf0e10cSrcweir //---------------------------------------------------------------------------
453cdf0e10cSrcweir // SkipBlanks
454cdf0e10cSrcweir //
455cdf0e10cSrcweir // Ueberspringt Leerzeichen
456cdf0e10cSrcweir
SkipBlanks(const String & rString,xub_StrLen & nPos)457cdf0e10cSrcweir inline void ImpSvNumberInputScan::SkipBlanks( const String& rString,
458cdf0e10cSrcweir xub_StrLen& nPos )
459cdf0e10cSrcweir {
460cdf0e10cSrcweir if ( nPos < rString.Len() )
461cdf0e10cSrcweir {
462cdf0e10cSrcweir register const sal_Unicode* p = rString.GetBuffer() + nPos;
463cdf0e10cSrcweir while ( *p == ' ' )
464cdf0e10cSrcweir {
465cdf0e10cSrcweir nPos++;
466cdf0e10cSrcweir p++;
467cdf0e10cSrcweir }
468cdf0e10cSrcweir }
469cdf0e10cSrcweir }
470cdf0e10cSrcweir
471cdf0e10cSrcweir
472cdf0e10cSrcweir //---------------------------------------------------------------------------
473cdf0e10cSrcweir // SkipString
474cdf0e10cSrcweir //
475cdf0e10cSrcweir // jump over rWhat in rString at nPos
476cdf0e10cSrcweir
SkipString(const String & rWhat,const String & rString,xub_StrLen & nPos)477cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::SkipString( const String& rWhat,
478cdf0e10cSrcweir const String& rString, xub_StrLen& nPos )
479cdf0e10cSrcweir {
480cdf0e10cSrcweir if ( StringContains( rWhat, rString, nPos ) )
481cdf0e10cSrcweir {
482cdf0e10cSrcweir nPos = nPos + rWhat.Len();
483cdf0e10cSrcweir return sal_True;
484cdf0e10cSrcweir }
485cdf0e10cSrcweir return sal_False;
486cdf0e10cSrcweir }
487cdf0e10cSrcweir
488cdf0e10cSrcweir
489cdf0e10cSrcweir //---------------------------------------------------------------------------
490cdf0e10cSrcweir // GetThousandSep
491cdf0e10cSrcweir //
492cdf0e10cSrcweir // recognizes exactly ,111 in {3} and {3,2} or ,11 in {3,2} grouping
493cdf0e10cSrcweir
GetThousandSep(const String & rString,xub_StrLen & nPos,sal_uInt16 nStringPos)494cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::GetThousandSep(
495cdf0e10cSrcweir const String& rString,
496cdf0e10cSrcweir xub_StrLen& nPos,
497cdf0e10cSrcweir sal_uInt16 nStringPos )
498cdf0e10cSrcweir {
499cdf0e10cSrcweir const String& rSep = pFormatter->GetNumThousandSep();
500cdf0e10cSrcweir // Is it an ordinary space instead of a non-breaking space?
501cdf0e10cSrcweir bool bSpaceBreak = rSep.GetChar(0) == 0xa0 && rString.GetChar(0) == 0x20 &&
502cdf0e10cSrcweir rSep.Len() == 1 && rString.Len() == 1;
503cdf0e10cSrcweir if (!( (rString == rSep || bSpaceBreak) // nothing else
504cdf0e10cSrcweir && nStringPos < nAnzStrings - 1 // safety first!
505cdf0e10cSrcweir && IsNum[nStringPos+1] )) // number follows
506cdf0e10cSrcweir return sal_False; // no? => out
507cdf0e10cSrcweir
508cdf0e10cSrcweir utl::DigitGroupingIterator aGrouping(
509cdf0e10cSrcweir pFormatter->GetLocaleData()->getDigitGrouping());
510cdf0e10cSrcweir // Match ,### in {3} or ,## in {3,2}
511cdf0e10cSrcweir /* FIXME: this could be refined to match ,## in {3,2} only if ,##,## or
512cdf0e10cSrcweir * ,##,### and to match ,### in {3,2} only if it's the last. However,
513cdf0e10cSrcweir * currently there is no track kept where group separators occur. In {3,2}
514cdf0e10cSrcweir * #,###,### and #,##,## would be valid input, which maybe isn't even bad
515cdf0e10cSrcweir * for #,###,###. Other combinations such as #,###,## maybe not. */
516cdf0e10cSrcweir xub_StrLen nLen = sStrArray[nStringPos+1].Len();
517cdf0e10cSrcweir if (nLen == aGrouping.get() // with 3 (or so) digits
518cdf0e10cSrcweir || nLen == aGrouping.advance().get() // or with 2 (or 3 or so) digits
519cdf0e10cSrcweir || nPosThousandString == nStringPos+1 // or concatenated
520cdf0e10cSrcweir )
521cdf0e10cSrcweir {
522cdf0e10cSrcweir nPos = nPos + rSep.Len();
523cdf0e10cSrcweir return sal_True;
524cdf0e10cSrcweir }
525cdf0e10cSrcweir return sal_False;
526cdf0e10cSrcweir }
527cdf0e10cSrcweir
528cdf0e10cSrcweir
529cdf0e10cSrcweir //---------------------------------------------------------------------------
530cdf0e10cSrcweir // GetLogical
531cdf0e10cSrcweir //
532cdf0e10cSrcweir // Conversion of text to logial value
533cdf0e10cSrcweir // "sal_True" => 1:
534cdf0e10cSrcweir // "sal_False"=> -1:
535cdf0e10cSrcweir // else => 0:
536cdf0e10cSrcweir
GetLogical(const String & rString)537cdf0e10cSrcweir short ImpSvNumberInputScan::GetLogical( const String& rString )
538cdf0e10cSrcweir {
539cdf0e10cSrcweir short res;
540cdf0e10cSrcweir
541cdf0e10cSrcweir const ImpSvNumberformatScan* pFS = pFormatter->GetFormatScanner();
542cdf0e10cSrcweir if ( rString == pFS->GetTrueString() )
543cdf0e10cSrcweir res = 1;
544cdf0e10cSrcweir else if ( rString == pFS->GetFalseString() )
545cdf0e10cSrcweir res = -1;
546cdf0e10cSrcweir else
547cdf0e10cSrcweir res = 0;
548cdf0e10cSrcweir
549cdf0e10cSrcweir return res;
550cdf0e10cSrcweir }
551cdf0e10cSrcweir
552cdf0e10cSrcweir
553cdf0e10cSrcweir //---------------------------------------------------------------------------
554cdf0e10cSrcweir // GetMonth
555cdf0e10cSrcweir //
556cdf0e10cSrcweir // Converts a string containing a month name (JAN, January) at nPos into the
557cdf0e10cSrcweir // month number (negative if abbreviated), returns 0 if nothing found
558cdf0e10cSrcweir
GetMonth(const String & rString,xub_StrLen & nPos)559cdf0e10cSrcweir short ImpSvNumberInputScan::GetMonth( const String& rString, xub_StrLen& nPos )
560cdf0e10cSrcweir {
561cdf0e10cSrcweir // #102136# The correct English form of month September abbreviated is
562cdf0e10cSrcweir // SEPT, but almost every data contains SEP instead.
563cdf0e10cSrcweir static const String aSeptCorrect( RTL_CONSTASCII_USTRINGPARAM( "SEPT" ) );
564cdf0e10cSrcweir static const String aSepShortened( RTL_CONSTASCII_USTRINGPARAM( "SEP" ) );
565cdf0e10cSrcweir
566cdf0e10cSrcweir short res = 0; // no month found
567cdf0e10cSrcweir
568cdf0e10cSrcweir if (rString.Len() > nPos) // only if needed
569cdf0e10cSrcweir {
570cdf0e10cSrcweir if ( !bTextInitialized )
571cdf0e10cSrcweir InitText();
572cdf0e10cSrcweir sal_Int16 nMonths = pFormatter->GetCalendar()->getNumberOfMonthsInYear();
573cdf0e10cSrcweir for ( sal_Int16 i = 0; i < nMonths; i++ )
574cdf0e10cSrcweir {
575cdf0e10cSrcweir if ( StringContains( pUpperMonthText[i], rString, nPos ) )
576cdf0e10cSrcweir { // full names first
577cdf0e10cSrcweir nPos = nPos + pUpperMonthText[i].Len();
578cdf0e10cSrcweir res = i+1;
579cdf0e10cSrcweir break; // for
580cdf0e10cSrcweir }
581cdf0e10cSrcweir else if ( StringContains( pUpperAbbrevMonthText[i], rString, nPos ) )
582cdf0e10cSrcweir { // abbreviated
583cdf0e10cSrcweir nPos = nPos + pUpperAbbrevMonthText[i].Len();
584cdf0e10cSrcweir res = sal::static_int_cast< short >(-(i+1)); // negative
585cdf0e10cSrcweir break; // for
586cdf0e10cSrcweir }
587cdf0e10cSrcweir else if ( i == 8 && pUpperAbbrevMonthText[i] == aSeptCorrect &&
588cdf0e10cSrcweir StringContains( aSepShortened, rString, nPos ) )
589cdf0e10cSrcweir { // #102136# SEPT/SEP
590cdf0e10cSrcweir nPos = nPos + aSepShortened.Len();
591cdf0e10cSrcweir res = sal::static_int_cast< short >(-(i+1)); // negative
592cdf0e10cSrcweir break; // for
593cdf0e10cSrcweir }
594cdf0e10cSrcweir }
595cdf0e10cSrcweir }
596cdf0e10cSrcweir
597cdf0e10cSrcweir return res;
598cdf0e10cSrcweir }
599cdf0e10cSrcweir
600cdf0e10cSrcweir
601cdf0e10cSrcweir //---------------------------------------------------------------------------
602cdf0e10cSrcweir // GetDayOfWeek
603cdf0e10cSrcweir //
604cdf0e10cSrcweir // Converts a string containing a DayOfWeek name (Mon, Monday) at nPos into the
605cdf0e10cSrcweir // DayOfWeek number + 1 (negative if abbreviated), returns 0 if nothing found
606cdf0e10cSrcweir
GetDayOfWeek(const String & rString,xub_StrLen & nPos)607cdf0e10cSrcweir int ImpSvNumberInputScan::GetDayOfWeek( const String& rString, xub_StrLen& nPos )
608cdf0e10cSrcweir {
609cdf0e10cSrcweir int res = 0; // no day found
610cdf0e10cSrcweir
611cdf0e10cSrcweir if (rString.Len() > nPos) // only if needed
612cdf0e10cSrcweir {
613cdf0e10cSrcweir if ( !bTextInitialized )
614cdf0e10cSrcweir InitText();
615cdf0e10cSrcweir sal_Int16 nDays = pFormatter->GetCalendar()->getNumberOfDaysInWeek();
616cdf0e10cSrcweir for ( sal_Int16 i = 0; i < nDays; i++ )
617cdf0e10cSrcweir {
618cdf0e10cSrcweir if ( StringContains( pUpperDayText[i], rString, nPos ) )
619cdf0e10cSrcweir { // full names first
620cdf0e10cSrcweir nPos = nPos + pUpperDayText[i].Len();
621cdf0e10cSrcweir res = i + 1;
622cdf0e10cSrcweir break; // for
623cdf0e10cSrcweir }
624cdf0e10cSrcweir if ( StringContains( pUpperAbbrevDayText[i], rString, nPos ) )
625cdf0e10cSrcweir { // abbreviated
626cdf0e10cSrcweir nPos = nPos + pUpperAbbrevDayText[i].Len();
627cdf0e10cSrcweir res = -(i + 1); // negative
628cdf0e10cSrcweir break; // for
629cdf0e10cSrcweir }
630cdf0e10cSrcweir }
631cdf0e10cSrcweir }
632cdf0e10cSrcweir
633cdf0e10cSrcweir return res;
634cdf0e10cSrcweir }
635cdf0e10cSrcweir
636cdf0e10cSrcweir
637cdf0e10cSrcweir //---------------------------------------------------------------------------
638cdf0e10cSrcweir // GetCurrency
639cdf0e10cSrcweir //
640c71adef7SDamjan Jovanovic // Reading a currency symbol
641cdf0e10cSrcweir // '$' => sal_True
642c71adef7SDamjan Jovanovic // else => sal_False
643cdf0e10cSrcweir
GetCurrency(const String & rString,xub_StrLen & nPos,const SvNumberformat * pFormat)644cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::GetCurrency( const String& rString, xub_StrLen& nPos,
645cdf0e10cSrcweir const SvNumberformat* pFormat )
646cdf0e10cSrcweir {
647cdf0e10cSrcweir if ( rString.Len() > nPos )
648cdf0e10cSrcweir {
649cdf0e10cSrcweir if ( !aUpperCurrSymbol.Len() )
650cdf0e10cSrcweir { // if no format specified the currency of the initialized formatter
651cdf0e10cSrcweir LanguageType eLang = (pFormat ? pFormat->GetLanguage() :
652cdf0e10cSrcweir pFormatter->GetLanguage());
653cdf0e10cSrcweir aUpperCurrSymbol = pFormatter->GetCharClass()->upper(
654cdf0e10cSrcweir SvNumberFormatter::GetCurrencyEntry( eLang ).GetSymbol() );
655cdf0e10cSrcweir }
656cdf0e10cSrcweir if ( StringContains( aUpperCurrSymbol, rString, nPos ) )
657cdf0e10cSrcweir {
658cdf0e10cSrcweir nPos = nPos + aUpperCurrSymbol.Len();
659cdf0e10cSrcweir return sal_True;
660cdf0e10cSrcweir }
661cdf0e10cSrcweir if ( pFormat )
662cdf0e10cSrcweir {
663cdf0e10cSrcweir String aSymbol, aExtension;
664cdf0e10cSrcweir if ( pFormat->GetNewCurrencySymbol( aSymbol, aExtension ) )
665cdf0e10cSrcweir {
666cdf0e10cSrcweir if ( aSymbol.Len() <= rString.Len() - nPos )
667cdf0e10cSrcweir {
668cdf0e10cSrcweir pFormatter->GetCharClass()->toUpper( aSymbol );
669cdf0e10cSrcweir if ( StringContains( aSymbol, rString, nPos ) )
670cdf0e10cSrcweir {
671cdf0e10cSrcweir nPos = nPos + aSymbol.Len();
672cdf0e10cSrcweir return sal_True;
673cdf0e10cSrcweir }
674cdf0e10cSrcweir }
675cdf0e10cSrcweir }
676cdf0e10cSrcweir }
677cdf0e10cSrcweir }
678cdf0e10cSrcweir
679cdf0e10cSrcweir return sal_False;
680cdf0e10cSrcweir }
681cdf0e10cSrcweir
682cdf0e10cSrcweir
683cdf0e10cSrcweir //---------------------------------------------------------------------------
684cdf0e10cSrcweir // GetTimeAmPm
685cdf0e10cSrcweir //
686cdf0e10cSrcweir // Lesen des Zeitsymbols (AM od. PM) f. kurze Zeitangabe
687cdf0e10cSrcweir //
688cdf0e10cSrcweir // Rueckgabe:
689cdf0e10cSrcweir // "AM" od. "PM" => sal_True
690cdf0e10cSrcweir // sonst => sal_False
691cdf0e10cSrcweir //
692cdf0e10cSrcweir // nAmPos:
693cdf0e10cSrcweir // "AM" => 1
694cdf0e10cSrcweir // "PM" => -1
695cdf0e10cSrcweir // sonst => 0
696cdf0e10cSrcweir
GetTimeAmPm(const String & rString,xub_StrLen & nPos)697cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::GetTimeAmPm( const String& rString, xub_StrLen& nPos )
698cdf0e10cSrcweir {
699cdf0e10cSrcweir
700cdf0e10cSrcweir if ( rString.Len() > nPos )
701cdf0e10cSrcweir {
702cdf0e10cSrcweir const CharClass* pChr = pFormatter->GetCharClass();
703cdf0e10cSrcweir const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
704cdf0e10cSrcweir if ( StringContains( pChr->upper( pLoc->getTimeAM() ), rString, nPos ) )
705cdf0e10cSrcweir {
706cdf0e10cSrcweir nAmPm = 1;
707cdf0e10cSrcweir nPos = nPos + pLoc->getTimeAM().Len();
708cdf0e10cSrcweir return sal_True;
709cdf0e10cSrcweir }
710cdf0e10cSrcweir else if ( StringContains( pChr->upper( pLoc->getTimePM() ), rString, nPos ) )
711cdf0e10cSrcweir {
712cdf0e10cSrcweir nAmPm = -1;
713cdf0e10cSrcweir nPos = nPos + pLoc->getTimePM().Len();
714cdf0e10cSrcweir return sal_True;
715cdf0e10cSrcweir }
716cdf0e10cSrcweir }
717cdf0e10cSrcweir
718cdf0e10cSrcweir return sal_False;
719cdf0e10cSrcweir }
720cdf0e10cSrcweir
721cdf0e10cSrcweir
722cdf0e10cSrcweir //---------------------------------------------------------------------------
723cdf0e10cSrcweir // GetDecSep
724cdf0e10cSrcweir //
725cdf0e10cSrcweir // Lesen eines Dezimaltrenners (',')
726cdf0e10cSrcweir // ',' => sal_True
727cdf0e10cSrcweir // sonst => sal_False
728cdf0e10cSrcweir
GetDecSep(const String & rString,xub_StrLen & nPos)729cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::GetDecSep( const String& rString, xub_StrLen& nPos )
730cdf0e10cSrcweir {
731cdf0e10cSrcweir if ( rString.Len() > nPos )
732cdf0e10cSrcweir {
733cdf0e10cSrcweir const String& rSep = pFormatter->GetNumDecimalSep();
734cdf0e10cSrcweir if ( rString.Equals( rSep, nPos, rSep.Len() ) )
735cdf0e10cSrcweir {
736cdf0e10cSrcweir nPos = nPos + rSep.Len();
737cdf0e10cSrcweir return sal_True;
738cdf0e10cSrcweir }
739cdf0e10cSrcweir }
740cdf0e10cSrcweir return sal_False;
741cdf0e10cSrcweir }
742cdf0e10cSrcweir
743cdf0e10cSrcweir
744cdf0e10cSrcweir //---------------------------------------------------------------------------
745cdf0e10cSrcweir // read a hundredth seconds separator
746cdf0e10cSrcweir
GetTime100SecSep(const String & rString,xub_StrLen & nPos)747cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::GetTime100SecSep( const String& rString, xub_StrLen& nPos )
748cdf0e10cSrcweir {
749cdf0e10cSrcweir if ( rString.Len() > nPos )
750cdf0e10cSrcweir {
751cdf0e10cSrcweir const String& rSep = pFormatter->GetLocaleData()->getTime100SecSep();
752cdf0e10cSrcweir if ( rString.Equals( rSep, nPos, rSep.Len() ) )
753cdf0e10cSrcweir {
754cdf0e10cSrcweir nPos = nPos + rSep.Len();
755cdf0e10cSrcweir return sal_True;
756cdf0e10cSrcweir }
757cdf0e10cSrcweir }
758cdf0e10cSrcweir return sal_False;
759cdf0e10cSrcweir }
760cdf0e10cSrcweir
761cdf0e10cSrcweir
762cdf0e10cSrcweir //---------------------------------------------------------------------------
763cdf0e10cSrcweir // GetSign
764cdf0e10cSrcweir //
765cdf0e10cSrcweir // Lesen eines Vorzeichens, auch Klammer !?!
766cdf0e10cSrcweir // '+' => 1
767cdf0e10cSrcweir // '-' => -1
768cdf0e10cSrcweir // '(' => -1, nNegCheck = 1
769cdf0e10cSrcweir // sonst => 0
770cdf0e10cSrcweir
GetSign(const String & rString,xub_StrLen & nPos)771cdf0e10cSrcweir int ImpSvNumberInputScan::GetSign( const String& rString, xub_StrLen& nPos )
772cdf0e10cSrcweir {
773cdf0e10cSrcweir if (rString.Len() > nPos)
774cdf0e10cSrcweir switch (rString.GetChar(nPos))
775cdf0e10cSrcweir {
776cdf0e10cSrcweir case '+':
777cdf0e10cSrcweir nPos++;
778cdf0e10cSrcweir return 1;
779cdf0e10cSrcweir case '(': // '(' aehnlich wie '-' ?!?
780cdf0e10cSrcweir nNegCheck = 1;
781cdf0e10cSrcweir //! fallthru
782cdf0e10cSrcweir case '-':
783cdf0e10cSrcweir nPos++;
784cdf0e10cSrcweir return -1;
785cdf0e10cSrcweir default:
786cdf0e10cSrcweir break;
787cdf0e10cSrcweir }
788cdf0e10cSrcweir
789cdf0e10cSrcweir return 0;
790cdf0e10cSrcweir }
791cdf0e10cSrcweir
792cdf0e10cSrcweir
793cdf0e10cSrcweir //---------------------------------------------------------------------------
794cdf0e10cSrcweir // GetESign
795cdf0e10cSrcweir //
796cdf0e10cSrcweir // Lesen eines Vorzeichens, gedacht fuer Exponent ?!?
797cdf0e10cSrcweir // '+' => 1
798cdf0e10cSrcweir // '-' => -1
799cdf0e10cSrcweir // sonst => 0
800cdf0e10cSrcweir
GetESign(const String & rString,xub_StrLen & nPos)801cdf0e10cSrcweir short ImpSvNumberInputScan::GetESign( const String& rString, xub_StrLen& nPos )
802cdf0e10cSrcweir {
803cdf0e10cSrcweir if (rString.Len() > nPos)
804cdf0e10cSrcweir switch (rString.GetChar(nPos))
805cdf0e10cSrcweir {
806cdf0e10cSrcweir case '+':
807cdf0e10cSrcweir nPos++;
808cdf0e10cSrcweir return 1;
809cdf0e10cSrcweir case '-':
810cdf0e10cSrcweir nPos++;
811cdf0e10cSrcweir return -1;
812cdf0e10cSrcweir default:
813cdf0e10cSrcweir break;
814cdf0e10cSrcweir }
815cdf0e10cSrcweir
816cdf0e10cSrcweir return 0;
817cdf0e10cSrcweir }
818cdf0e10cSrcweir
819cdf0e10cSrcweir
820cdf0e10cSrcweir //---------------------------------------------------------------------------
821cdf0e10cSrcweir // GetNextNumber
822cdf0e10cSrcweir //
823cdf0e10cSrcweir // i counts string portions, j counts numbers thereof.
824cdf0e10cSrcweir // It should had been called SkipNumber instead.
825cdf0e10cSrcweir
GetNextNumber(sal_uInt16 & i,sal_uInt16 & j)826cdf0e10cSrcweir inline sal_Bool ImpSvNumberInputScan::GetNextNumber( sal_uInt16& i, sal_uInt16& j )
827cdf0e10cSrcweir {
828cdf0e10cSrcweir if ( i < nAnzStrings && IsNum[i] )
829cdf0e10cSrcweir {
830cdf0e10cSrcweir j++;
831cdf0e10cSrcweir i++;
832cdf0e10cSrcweir return sal_True;
833cdf0e10cSrcweir }
834cdf0e10cSrcweir return sal_False;
835cdf0e10cSrcweir }
836cdf0e10cSrcweir
837cdf0e10cSrcweir
838cdf0e10cSrcweir //---------------------------------------------------------------------------
839cdf0e10cSrcweir // GetTimeRef
840cdf0e10cSrcweir
GetTimeRef(double & fOutNumber,sal_uInt16 nIndex,sal_uInt16 nAnz)841cdf0e10cSrcweir void ImpSvNumberInputScan::GetTimeRef(
842cdf0e10cSrcweir double& fOutNumber,
843cdf0e10cSrcweir sal_uInt16 nIndex, // j-value of the first numeric time part of input, default 0
844cdf0e10cSrcweir sal_uInt16 nAnz ) // count of numeric time parts
845cdf0e10cSrcweir {
846cdf0e10cSrcweir sal_uInt16 nHour;
847cdf0e10cSrcweir sal_uInt16 nMinute = 0;
848cdf0e10cSrcweir sal_uInt16 nSecond = 0;
849cdf0e10cSrcweir double fSecond100 = 0.0;
850cdf0e10cSrcweir sal_uInt16 nStartIndex = nIndex;
851cdf0e10cSrcweir
852cdf0e10cSrcweir if (nTimezonePos)
853cdf0e10cSrcweir {
854cdf0e10cSrcweir // find first timezone number index and adjust count
855cdf0e10cSrcweir for (sal_uInt16 j=0; j<nAnzNums; ++j)
856cdf0e10cSrcweir {
857cdf0e10cSrcweir if (nNums[j] == nTimezonePos)
858cdf0e10cSrcweir {
859cdf0e10cSrcweir // nAnz is not total count, but count of time relevant strings.
860cdf0e10cSrcweir if (nStartIndex < j && j - nStartIndex < nAnz)
861cdf0e10cSrcweir nAnz = j - nStartIndex;
862cdf0e10cSrcweir break; // for
863cdf0e10cSrcweir }
864cdf0e10cSrcweir }
865cdf0e10cSrcweir }
866cdf0e10cSrcweir
867cdf0e10cSrcweir if (nDecPos == 2 && (nAnz == 3 || nAnz == 2)) // 20:45.5 or 45.5
868cdf0e10cSrcweir nHour = 0;
869cdf0e10cSrcweir else if (nIndex - nStartIndex < nAnz)
870cdf0e10cSrcweir nHour = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
871cdf0e10cSrcweir else
872cdf0e10cSrcweir {
873cdf0e10cSrcweir nHour = 0;
874cdf0e10cSrcweir DBG_ERRORFILE( "ImpSvNumberInputScan::GetTimeRef: bad number index");
875cdf0e10cSrcweir }
876cdf0e10cSrcweir if (nDecPos == 2 && nAnz == 2) // 45.5
877cdf0e10cSrcweir nMinute = 0;
878cdf0e10cSrcweir else if (nIndex - nStartIndex < nAnz)
879cdf0e10cSrcweir nMinute = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
880cdf0e10cSrcweir if (nIndex - nStartIndex < nAnz)
881cdf0e10cSrcweir nSecond = (sal_uInt16) sStrArray[nNums[nIndex++]].ToInt32();
882cdf0e10cSrcweir if (nIndex - nStartIndex < nAnz)
883cdf0e10cSrcweir fSecond100 = StringToDouble( sStrArray[nNums[nIndex]], sal_True );
884cdf0e10cSrcweir if (nAmPm == -1 && nHour != 12) // PM
885cdf0e10cSrcweir nHour += 12;
886cdf0e10cSrcweir else if (nAmPm == 1 && nHour == 12) // 12 AM
887cdf0e10cSrcweir nHour = 0;
888cdf0e10cSrcweir
889cdf0e10cSrcweir fOutNumber = ((double)nHour*3600 +
890cdf0e10cSrcweir (double)nMinute*60 +
891cdf0e10cSrcweir (double)nSecond +
892cdf0e10cSrcweir fSecond100)/86400.0;
893cdf0e10cSrcweir }
894cdf0e10cSrcweir
895cdf0e10cSrcweir
896cdf0e10cSrcweir //---------------------------------------------------------------------------
897cdf0e10cSrcweir // ImplGetDay
898cdf0e10cSrcweir
ImplGetDay(sal_uInt16 nIndex)899cdf0e10cSrcweir sal_uInt16 ImpSvNumberInputScan::ImplGetDay( sal_uInt16 nIndex )
900cdf0e10cSrcweir {
901cdf0e10cSrcweir sal_uInt16 nRes = 0;
902cdf0e10cSrcweir
903cdf0e10cSrcweir if (sStrArray[nNums[nIndex]].Len() <= 2)
904cdf0e10cSrcweir {
905cdf0e10cSrcweir sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
906cdf0e10cSrcweir if (nNum <= 31)
907cdf0e10cSrcweir nRes = nNum;
908cdf0e10cSrcweir }
909cdf0e10cSrcweir
910cdf0e10cSrcweir return nRes;
911cdf0e10cSrcweir }
912cdf0e10cSrcweir
913cdf0e10cSrcweir
914cdf0e10cSrcweir //---------------------------------------------------------------------------
915cdf0e10cSrcweir // ImplGetMonth
916cdf0e10cSrcweir
ImplGetMonth(sal_uInt16 nIndex)917cdf0e10cSrcweir sal_uInt16 ImpSvNumberInputScan::ImplGetMonth( sal_uInt16 nIndex )
918cdf0e10cSrcweir {
919cdf0e10cSrcweir // preset invalid month number
920cdf0e10cSrcweir sal_uInt16 nRes = pFormatter->GetCalendar()->getNumberOfMonthsInYear();
921cdf0e10cSrcweir
922cdf0e10cSrcweir if (sStrArray[nNums[nIndex]].Len() <= 2)
923cdf0e10cSrcweir {
924cdf0e10cSrcweir sal_uInt16 nNum = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
925cdf0e10cSrcweir if ( 0 < nNum && nNum <= nRes )
926cdf0e10cSrcweir nRes = nNum - 1; // zero based for CalendarFieldIndex::MONTH
927cdf0e10cSrcweir }
928cdf0e10cSrcweir
929cdf0e10cSrcweir return nRes;
930cdf0e10cSrcweir }
931cdf0e10cSrcweir
932cdf0e10cSrcweir
933cdf0e10cSrcweir //---------------------------------------------------------------------------
934cdf0e10cSrcweir // ImplGetYear
935cdf0e10cSrcweir //
936cdf0e10cSrcweir // 30 -> 1930, 29 -> 2029, oder 56 -> 1756, 55 -> 1855, ...
937cdf0e10cSrcweir
ImplGetYear(sal_uInt16 nIndex)938cdf0e10cSrcweir sal_uInt16 ImpSvNumberInputScan::ImplGetYear( sal_uInt16 nIndex )
939cdf0e10cSrcweir {
940cdf0e10cSrcweir sal_uInt16 nYear = 0;
941cdf0e10cSrcweir
942cdf0e10cSrcweir if (sStrArray[nNums[nIndex]].Len() <= 4)
943cdf0e10cSrcweir {
944cdf0e10cSrcweir nYear = (sal_uInt16) sStrArray[nNums[nIndex]].ToInt32();
945cdf0e10cSrcweir nYear = SvNumberFormatter::ExpandTwoDigitYear( nYear, nYear2000 );
946cdf0e10cSrcweir }
947cdf0e10cSrcweir
948cdf0e10cSrcweir return nYear;
949cdf0e10cSrcweir }
950cdf0e10cSrcweir
951cdf0e10cSrcweir //---------------------------------------------------------------------------
952cdf0e10cSrcweir
MayBeIso8601()953cdf0e10cSrcweir bool ImpSvNumberInputScan::MayBeIso8601()
954cdf0e10cSrcweir {
955cdf0e10cSrcweir if (nMayBeIso8601 == 0)
956cdf0e10cSrcweir {
957cdf0e10cSrcweir if (nAnzNums >= 3 && nNums[0] < nAnzStrings &&
958cdf0e10cSrcweir sStrArray[nNums[0]].ToInt32() > 31)
959cdf0e10cSrcweir nMayBeIso8601 = 1;
960cdf0e10cSrcweir else
961cdf0e10cSrcweir nMayBeIso8601 = 2;
962cdf0e10cSrcweir }
963cdf0e10cSrcweir return nMayBeIso8601 == 1;
964cdf0e10cSrcweir }
965cdf0e10cSrcweir
966cdf0e10cSrcweir //---------------------------------------------------------------------------
967cdf0e10cSrcweir // GetDateRef
968cdf0e10cSrcweir
GetDateRef(double & fDays,sal_uInt16 & nCounter,const SvNumberformat * pFormat)969cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::GetDateRef( double& fDays, sal_uInt16& nCounter,
970cdf0e10cSrcweir const SvNumberformat* pFormat )
971cdf0e10cSrcweir {
972cdf0e10cSrcweir using namespace ::com::sun::star::i18n;
973cdf0e10cSrcweir NfEvalDateFormat eEDF;
974cdf0e10cSrcweir int nFormatOrder;
975cdf0e10cSrcweir if ( pFormat && ((pFormat->GetType() & NUMBERFORMAT_DATE) == NUMBERFORMAT_DATE) )
976cdf0e10cSrcweir {
977cdf0e10cSrcweir eEDF = pFormatter->GetEvalDateFormat();
978cdf0e10cSrcweir switch ( eEDF )
979cdf0e10cSrcweir {
980cdf0e10cSrcweir case NF_EVALDATEFORMAT_INTL :
981cdf0e10cSrcweir case NF_EVALDATEFORMAT_FORMAT :
982cdf0e10cSrcweir nFormatOrder = 1; // only one loop
983cdf0e10cSrcweir break;
984cdf0e10cSrcweir default:
985cdf0e10cSrcweir nFormatOrder = 2;
986cdf0e10cSrcweir if ( nMatchedAllStrings )
987cdf0e10cSrcweir eEDF = NF_EVALDATEFORMAT_FORMAT_INTL;
988cdf0e10cSrcweir // we have a complete match, use it
989cdf0e10cSrcweir }
990cdf0e10cSrcweir }
991cdf0e10cSrcweir else
992cdf0e10cSrcweir {
993cdf0e10cSrcweir eEDF = NF_EVALDATEFORMAT_INTL;
994cdf0e10cSrcweir nFormatOrder = 1;
995cdf0e10cSrcweir }
996cdf0e10cSrcweir sal_Bool res = sal_True;
997cdf0e10cSrcweir
998cdf0e10cSrcweir const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
999cdf0e10cSrcweir CalendarWrapper* pCal = pFormatter->GetCalendar();
1000cdf0e10cSrcweir for ( int nTryOrder = 1; nTryOrder <= nFormatOrder; nTryOrder++ )
1001cdf0e10cSrcweir {
1002cdf0e10cSrcweir pCal->setGregorianDateTime( Date() ); // today
1003cdf0e10cSrcweir String aOrgCalendar; // empty => not changed yet
1004cdf0e10cSrcweir DateFormat DateFmt;
1005cdf0e10cSrcweir sal_Bool bFormatTurn;
1006cdf0e10cSrcweir switch ( eEDF )
1007cdf0e10cSrcweir {
1008cdf0e10cSrcweir case NF_EVALDATEFORMAT_INTL :
1009cdf0e10cSrcweir bFormatTurn = sal_False;
1010cdf0e10cSrcweir DateFmt = pLoc->getDateFormat();
1011cdf0e10cSrcweir break;
1012cdf0e10cSrcweir case NF_EVALDATEFORMAT_FORMAT :
1013cdf0e10cSrcweir bFormatTurn = sal_True;
1014cdf0e10cSrcweir DateFmt = pFormat->GetDateOrder();
1015cdf0e10cSrcweir break;
1016cdf0e10cSrcweir case NF_EVALDATEFORMAT_INTL_FORMAT :
1017cdf0e10cSrcweir if ( nTryOrder == 1 )
1018cdf0e10cSrcweir {
1019cdf0e10cSrcweir bFormatTurn = sal_False;
1020cdf0e10cSrcweir DateFmt = pLoc->getDateFormat();
1021cdf0e10cSrcweir }
1022cdf0e10cSrcweir else
1023cdf0e10cSrcweir {
1024cdf0e10cSrcweir bFormatTurn = sal_True;
1025cdf0e10cSrcweir DateFmt = pFormat->GetDateOrder();
1026cdf0e10cSrcweir }
1027cdf0e10cSrcweir break;
1028cdf0e10cSrcweir case NF_EVALDATEFORMAT_FORMAT_INTL :
1029cdf0e10cSrcweir if ( nTryOrder == 2 )
1030cdf0e10cSrcweir {
1031cdf0e10cSrcweir bFormatTurn = sal_False;
1032cdf0e10cSrcweir DateFmt = pLoc->getDateFormat();
1033cdf0e10cSrcweir }
1034cdf0e10cSrcweir else
1035cdf0e10cSrcweir {
1036cdf0e10cSrcweir bFormatTurn = sal_True;
1037cdf0e10cSrcweir DateFmt = pFormat->GetDateOrder();
1038cdf0e10cSrcweir }
1039cdf0e10cSrcweir break;
1040cdf0e10cSrcweir default:
1041cdf0e10cSrcweir DBG_ERROR( "ImpSvNumberInputScan::GetDateRef: unknown NfEvalDateFormat" );
1042cdf0e10cSrcweir DateFmt = YMD;
1043cdf0e10cSrcweir bFormatTurn = sal_False;
1044cdf0e10cSrcweir }
1045cdf0e10cSrcweir if ( bFormatTurn )
1046cdf0e10cSrcweir {
1047cdf0e10cSrcweir #if 0
1048cdf0e10cSrcweir /* TODO:
1049cdf0e10cSrcweir We are currently not able to fully support a switch to another calendar during
1050cdf0e10cSrcweir input for the following reasons:
1051cdf0e10cSrcweir 1. We do have a problem if both (locale's default and format's) calendars
1052cdf0e10cSrcweir define the same YMD order and use the same date separator, there is no way
1053cdf0e10cSrcweir to distinguish between them if the input results in valid calendar input for
1054cdf0e10cSrcweir both calendars. How to solve? Would NfEvalDateFormat be sufficient? Should
1055cdf0e10cSrcweir it always be set to NF_EVALDATEFORMAT_FORMAT_INTL and thus the format's
1056cdf0e10cSrcweir calendar be preferred? This could be confusing if a Calc cell was formatted
1057cdf0e10cSrcweir different to the locale's default and has no content yet, then the user has
1058cdf0e10cSrcweir no clue about the format or calendar being set.
1059cdf0e10cSrcweir 2. In Calc cell edit mode a date is always displayed and edited using the
1060cdf0e10cSrcweir default edit format of the default calendar (normally being Gregorian). If
1061cdf0e10cSrcweir input was ambiguous due to issue #1 we'd need a mechanism to tell that a
1062cdf0e10cSrcweir date was edited and not newly entered. Not feasible. Otherwise we'd need a
1063cdf0e10cSrcweir mechanism to use a specific edit format with a specific calendar according
1064cdf0e10cSrcweir to the format set.
1065cdf0e10cSrcweir 3. For some calendars like Japanese Gengou we'd need era input, which isn't
1066cdf0e10cSrcweir implemented at all. Though this is a rare and special case, forcing a
1067cdf0e10cSrcweir calendar dependent edit format as suggested in item #2 might require era
1068cdf0e10cSrcweir input, if it shouldn't result in a fallback to Gregorian calendar.
1069cdf0e10cSrcweir 4. Last and least: the GetMonth() method currently only matches month names of
1070cdf0e10cSrcweir the default calendar. Alternating month names of the actual format's
1071cdf0e10cSrcweir calendar would have to be implemented. No problem.
1072cdf0e10cSrcweir
1073cdf0e10cSrcweir */
1074cdf0e10cSrcweir if ( pFormat->IsOtherCalendar( nStringScanNumFor ) )
1075cdf0e10cSrcweir pFormat->SwitchToOtherCalendar( aOrgCalendar, fOrgDateTime );
1076cdf0e10cSrcweir else
1077cdf0e10cSrcweir pFormat->SwitchToSpecifiedCalendar( aOrgCalendar, fOrgDateTime,
1078cdf0e10cSrcweir nStringScanNumFor );
1079cdf0e10cSrcweir #endif
1080cdf0e10cSrcweir }
1081cdf0e10cSrcweir
1082cdf0e10cSrcweir res = sal_True;
1083cdf0e10cSrcweir nCounter = 0;
1084cdf0e10cSrcweir // For incomplete dates, always assume first day of month if not specified.
1085cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
1086cdf0e10cSrcweir
1087cdf0e10cSrcweir switch (nAnzNums) // count of numbers in string
1088cdf0e10cSrcweir {
1089cdf0e10cSrcweir case 0: // none
1090cdf0e10cSrcweir if (nMonthPos) // only month (Jan)
1091cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1092cdf0e10cSrcweir else
1093cdf0e10cSrcweir res = sal_False;
1094cdf0e10cSrcweir break;
1095cdf0e10cSrcweir
1096cdf0e10cSrcweir case 1: // only one number
1097cdf0e10cSrcweir nCounter = 1;
1098cdf0e10cSrcweir switch (nMonthPos) // where is the month
1099cdf0e10cSrcweir {
1100cdf0e10cSrcweir case 0: // not found => only day entered
1101cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1102cdf0e10cSrcweir break;
1103cdf0e10cSrcweir case 1: // month at the beginning (Jan 01)
1104cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1105cdf0e10cSrcweir switch (DateFmt)
1106cdf0e10cSrcweir {
1107cdf0e10cSrcweir case MDY:
1108cdf0e10cSrcweir case YMD:
1109cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1110cdf0e10cSrcweir break;
1111cdf0e10cSrcweir case DMY:
1112cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1113cdf0e10cSrcweir break;
1114cdf0e10cSrcweir default:
1115cdf0e10cSrcweir res = sal_False;
1116cdf0e10cSrcweir break;
1117cdf0e10cSrcweir }
1118cdf0e10cSrcweir break;
1119cdf0e10cSrcweir case 3: // month at the end (10 Jan)
1120cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1121cdf0e10cSrcweir switch (DateFmt)
1122cdf0e10cSrcweir {
1123cdf0e10cSrcweir case DMY:
1124cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1125cdf0e10cSrcweir break;
1126cdf0e10cSrcweir case YMD:
1127cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1128cdf0e10cSrcweir break;
1129cdf0e10cSrcweir default:
1130cdf0e10cSrcweir res = sal_False;
1131cdf0e10cSrcweir break;
1132cdf0e10cSrcweir }
1133cdf0e10cSrcweir break;
1134cdf0e10cSrcweir default:
1135cdf0e10cSrcweir res = sal_False;
1136cdf0e10cSrcweir break;
1137cdf0e10cSrcweir } // switch (nMonthPos)
1138cdf0e10cSrcweir break;
1139cdf0e10cSrcweir
1140cdf0e10cSrcweir case 2: // 2 numbers
1141cdf0e10cSrcweir nCounter = 2;
1142cdf0e10cSrcweir switch (nMonthPos) // where is the month
1143cdf0e10cSrcweir {
1144cdf0e10cSrcweir case 0: // not found
1145cdf0e10cSrcweir {
1146cdf0e10cSrcweir bool bHadExact;
1147cdf0e10cSrcweir sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0);
1148cdf0e10cSrcweir if ( 0xff < nExactDateOrder && nExactDateOrder <= 0xffff )
1149cdf0e10cSrcweir { // formatted as date and exactly 2 parts
1150cdf0e10cSrcweir bHadExact = true;
1151cdf0e10cSrcweir switch ( (nExactDateOrder >> 8) & 0xff )
1152cdf0e10cSrcweir {
1153cdf0e10cSrcweir case 'Y':
1154cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1155cdf0e10cSrcweir break;
1156cdf0e10cSrcweir case 'M':
1157cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1158cdf0e10cSrcweir break;
1159cdf0e10cSrcweir case 'D':
1160cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1161cdf0e10cSrcweir break;
1162cdf0e10cSrcweir default:
1163cdf0e10cSrcweir bHadExact = false;
1164cdf0e10cSrcweir }
1165cdf0e10cSrcweir switch ( nExactDateOrder & 0xff )
1166cdf0e10cSrcweir {
1167cdf0e10cSrcweir case 'Y':
1168cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1169cdf0e10cSrcweir break;
1170cdf0e10cSrcweir case 'M':
1171cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
1172cdf0e10cSrcweir break;
1173cdf0e10cSrcweir case 'D':
1174cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1175cdf0e10cSrcweir break;
1176cdf0e10cSrcweir default:
1177cdf0e10cSrcweir bHadExact = false;
1178cdf0e10cSrcweir }
1179cdf0e10cSrcweir }
1180cdf0e10cSrcweir else
1181cdf0e10cSrcweir bHadExact = false;
1182cdf0e10cSrcweir if ( !bHadExact || !pCal->isValid() )
1183cdf0e10cSrcweir {
1184cdf0e10cSrcweir if ( !bHadExact && nExactDateOrder )
1185cdf0e10cSrcweir pCal->setGregorianDateTime( Date() ); // reset today
1186cdf0e10cSrcweir switch (DateFmt)
1187cdf0e10cSrcweir {
1188cdf0e10cSrcweir case MDY:
1189cdf0e10cSrcweir // M D
1190cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1191cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1192cdf0e10cSrcweir if ( !pCal->isValid() ) // 2nd try
1193cdf0e10cSrcweir { // M Y
1194cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
1195cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1196cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1197cdf0e10cSrcweir }
1198cdf0e10cSrcweir break;
1199cdf0e10cSrcweir case DMY:
1200cdf0e10cSrcweir // D M
1201cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1202cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
1203cdf0e10cSrcweir if ( !pCal->isValid() ) // 2nd try
1204cdf0e10cSrcweir { // M Y
1205cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
1206cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1207cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1208cdf0e10cSrcweir }
1209cdf0e10cSrcweir break;
1210cdf0e10cSrcweir case YMD:
1211cdf0e10cSrcweir // M D
1212cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1213cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1214cdf0e10cSrcweir if ( !pCal->isValid() ) // 2nd try
1215cdf0e10cSrcweir { // Y M
1216cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, 1 );
1217cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
1218cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1219cdf0e10cSrcweir }
1220cdf0e10cSrcweir break;
1221cdf0e10cSrcweir default:
1222cdf0e10cSrcweir res = sal_False;
1223cdf0e10cSrcweir break;
1224cdf0e10cSrcweir }
1225cdf0e10cSrcweir }
1226cdf0e10cSrcweir }
1227cdf0e10cSrcweir break;
1228cdf0e10cSrcweir case 1: // month at the beginning (Jan 01 01)
1229cdf0e10cSrcweir {
1230cdf0e10cSrcweir // The input is valid as MDY in almost any
1231cdf0e10cSrcweir // constellation, there is no date order (M)YD except if
1232cdf0e10cSrcweir // set in a format applied.
1233cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1234cdf0e10cSrcweir sal_uInt32 nExactDateOrder = (bFormatTurn ? pFormat->GetExactDateOrder() : 0);
1235cdf0e10cSrcweir if ((((nExactDateOrder >> 8) & 0xff) == 'Y') && ((nExactDateOrder & 0xff) == 'D'))
1236cdf0e10cSrcweir {
1237cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1238cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1239cdf0e10cSrcweir }
1240cdf0e10cSrcweir else
1241cdf0e10cSrcweir {
1242cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1243cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1244cdf0e10cSrcweir }
1245cdf0e10cSrcweir }
1246cdf0e10cSrcweir break;
1247cdf0e10cSrcweir case 2: // month in the middle (10 Jan 94)
1248cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1249cdf0e10cSrcweir switch (DateFmt)
1250cdf0e10cSrcweir {
1251cdf0e10cSrcweir case MDY: // yes, "10-Jan-94" is valid
1252cdf0e10cSrcweir case DMY:
1253cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1254cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1255cdf0e10cSrcweir break;
1256cdf0e10cSrcweir case YMD:
1257cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1258cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1259cdf0e10cSrcweir break;
1260cdf0e10cSrcweir default:
1261cdf0e10cSrcweir res = sal_False;
1262cdf0e10cSrcweir break;
1263cdf0e10cSrcweir }
1264cdf0e10cSrcweir break;
1265cdf0e10cSrcweir default: // else, e.g. month at the end (94 10 Jan)
1266cdf0e10cSrcweir res = sal_False;
1267cdf0e10cSrcweir break;
1268cdf0e10cSrcweir } // switch (nMonthPos)
1269cdf0e10cSrcweir break;
1270cdf0e10cSrcweir
1271cdf0e10cSrcweir default: // more than two numbers (31.12.94 8:23) (31.12. 8:23)
1272cdf0e10cSrcweir switch (nMonthPos) // where is the month
1273cdf0e10cSrcweir {
1274cdf0e10cSrcweir case 0: // not found
1275cdf0e10cSrcweir {
1276cdf0e10cSrcweir nCounter = 3;
1277cdf0e10cSrcweir if ( nTimePos > 1 )
1278cdf0e10cSrcweir { // find first time number index (should only be 3 or 2 anyway)
1279cdf0e10cSrcweir for ( sal_uInt16 j = 0; j < nAnzNums; j++ )
1280cdf0e10cSrcweir {
1281cdf0e10cSrcweir if ( nNums[j] == nTimePos - 2 )
1282cdf0e10cSrcweir {
1283cdf0e10cSrcweir nCounter = j;
1284cdf0e10cSrcweir break; // for
1285cdf0e10cSrcweir }
1286cdf0e10cSrcweir }
1287cdf0e10cSrcweir }
1288cdf0e10cSrcweir // ISO 8601 yyyy-mm-dd forced recognition
1289cdf0e10cSrcweir DateFormat eDF = (MayBeIso8601() ? YMD : DateFmt);
1290cdf0e10cSrcweir switch (eDF)
1291cdf0e10cSrcweir {
1292cdf0e10cSrcweir case MDY:
1293cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1294cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(0) );
1295cdf0e10cSrcweir if ( nCounter > 2 )
1296cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(2) );
1297cdf0e10cSrcweir break;
1298cdf0e10cSrcweir case DMY:
1299cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1300cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
1301cdf0e10cSrcweir if ( nCounter > 2 )
1302cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(2) );
1303cdf0e10cSrcweir break;
1304cdf0e10cSrcweir case YMD:
1305cdf0e10cSrcweir if ( nCounter > 2 )
1306cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(2) );
1307cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, ImplGetMonth(1) );
1308cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1309cdf0e10cSrcweir break;
1310cdf0e10cSrcweir default:
1311cdf0e10cSrcweir res = sal_False;
1312cdf0e10cSrcweir break;
1313cdf0e10cSrcweir }
1314cdf0e10cSrcweir }
1315cdf0e10cSrcweir break;
1316cdf0e10cSrcweir case 1: // month at the beginning (Jan 01 01 8:23)
1317cdf0e10cSrcweir nCounter = 2;
1318cdf0e10cSrcweir switch (DateFmt)
1319cdf0e10cSrcweir {
1320cdf0e10cSrcweir case MDY:
1321cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1322cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1323cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1324cdf0e10cSrcweir break;
1325cdf0e10cSrcweir default:
1326cdf0e10cSrcweir res = sal_False;
1327cdf0e10cSrcweir break;
1328cdf0e10cSrcweir }
1329cdf0e10cSrcweir break;
1330cdf0e10cSrcweir case 2: // month in the middle (10 Jan 94 8:23)
1331cdf0e10cSrcweir nCounter = 2;
1332cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::MONTH, Abs(nMonth)-1 );
1333cdf0e10cSrcweir switch (DateFmt)
1334cdf0e10cSrcweir {
1335cdf0e10cSrcweir case DMY:
1336cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(0) );
1337cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(1) );
1338cdf0e10cSrcweir break;
1339cdf0e10cSrcweir case YMD:
1340cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::DAY_OF_MONTH, ImplGetDay(1) );
1341cdf0e10cSrcweir pCal->setValue( CalendarFieldIndex::YEAR, ImplGetYear(0) );
1342cdf0e10cSrcweir break;
1343cdf0e10cSrcweir default:
1344cdf0e10cSrcweir res = sal_False;
1345cdf0e10cSrcweir break;
1346cdf0e10cSrcweir }
1347cdf0e10cSrcweir break;
1348cdf0e10cSrcweir default: // else, e.g. month at the end (94 10 Jan 8:23)
1349cdf0e10cSrcweir nCounter = 2;
1350cdf0e10cSrcweir res = sal_False;
1351cdf0e10cSrcweir break;
1352cdf0e10cSrcweir } // switch (nMonthPos)
1353cdf0e10cSrcweir break;
1354cdf0e10cSrcweir } // switch (nAnzNums)
1355cdf0e10cSrcweir
1356cdf0e10cSrcweir if ( res && pCal->isValid() )
1357cdf0e10cSrcweir {
1358cdf0e10cSrcweir double fDiff = DateTime(*pNullDate) - pCal->getEpochStart();
1359cdf0e10cSrcweir fDays = ::rtl::math::approxFloor( pCal->getLocalDateTime() );
1360cdf0e10cSrcweir fDays -= fDiff;
1361cdf0e10cSrcweir nTryOrder = nFormatOrder; // break for
1362cdf0e10cSrcweir }
1363cdf0e10cSrcweir else
1364cdf0e10cSrcweir res = sal_False;
1365cdf0e10cSrcweir
1366cdf0e10cSrcweir if ( aOrgCalendar.Len() )
1367cdf0e10cSrcweir pCal->loadCalendar( aOrgCalendar, pLoc->getLocale() ); // restore calendar
1368cdf0e10cSrcweir
1369cdf0e10cSrcweir #if NF_TEST_CALENDAR
1370cdf0e10cSrcweir {
1371cdf0e10cSrcweir using namespace ::com::sun::star;
1372cdf0e10cSrcweir struct entry { const char* lan; const char* cou; const char* cal; };
1373cdf0e10cSrcweir const entry cals[] = {
1374cdf0e10cSrcweir { "en", "US", "gregorian" },
1375cdf0e10cSrcweir { "ar", "TN", "hijri" },
1376cdf0e10cSrcweir { "he", "IL", "jewish" },
1377cdf0e10cSrcweir { "ja", "JP", "gengou" },
1378cdf0e10cSrcweir { "ko", "KR", "hanja_yoil" },
1379cdf0e10cSrcweir { "th", "TH", "buddhist" },
1380cdf0e10cSrcweir { "zh", "TW", "ROC" },
1381cdf0e10cSrcweir {0,0,0}
1382cdf0e10cSrcweir };
1383cdf0e10cSrcweir lang::Locale aLocale;
1384cdf0e10cSrcweir sal_Bool bValid;
1385cdf0e10cSrcweir sal_Int16 nDay, nMyMonth, nYear, nHour, nMinute, nSecond;
1386cdf0e10cSrcweir sal_Int16 nDaySet, nMonthSet, nYearSet, nHourSet, nMinuteSet, nSecondSet;
1387cdf0e10cSrcweir sal_Int16 nZO, nDST1, nDST2, nDST, nZOmillis, nDST1millis, nDST2millis, nDSTmillis;
1388cdf0e10cSrcweir sal_Int32 nZoneInMillis, nDST1InMillis, nDST2InMillis;
1389cdf0e10cSrcweir uno::Reference< lang::XMultiServiceFactory > xSMgr =
1390cdf0e10cSrcweir ::comphelper::getProcessServiceFactory();
1391cdf0e10cSrcweir uno::Reference< ::com::sun::star::i18n::XExtendedCalendar > xCal(
1392cdf0e10cSrcweir xSMgr->createInstance( ::rtl::OUString(
1393cdf0e10cSrcweir RTL_CONSTASCII_USTRINGPARAM(
1394cdf0e10cSrcweir "com.sun.star.i18n.LocaleCalendar" ) ) ),
1395cdf0e10cSrcweir uno::UNO_QUERY );
1396cdf0e10cSrcweir for ( const entry* p = cals; p->lan; ++p )
1397cdf0e10cSrcweir {
1398cdf0e10cSrcweir aLocale.Language = ::rtl::OUString::createFromAscii( p->lan );
1399cdf0e10cSrcweir aLocale.Country = ::rtl::OUString::createFromAscii( p->cou );
1400cdf0e10cSrcweir xCal->loadCalendar( ::rtl::OUString::createFromAscii( p->cal ),
1401cdf0e10cSrcweir aLocale );
1402cdf0e10cSrcweir double nDateTime = 0.0; // 1-Jan-1970 00:00:00
1403cdf0e10cSrcweir nZO = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET );
1404cdf0e10cSrcweir nZOmillis = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS );
1405cdf0e10cSrcweir nZoneInMillis = static_cast<sal_Int32>(nZO) * 60000 +
1406cdf0e10cSrcweir (nZO < 0 ? -1 : 1) * static_cast<sal_uInt16>(nZOmillis);
1407cdf0e10cSrcweir nDST1 = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
1408cdf0e10cSrcweir nDST1millis = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
1409cdf0e10cSrcweir nDST1InMillis = static_cast<sal_Int32>(nDST1) * 60000 +
1410cdf0e10cSrcweir (nDST1 < 0 ? -1 : 1) * static_cast<sal_uInt16>(nDST1millis);
1411cdf0e10cSrcweir nDateTime -= (double)(nZoneInMillis + nDST1InMillis) / 1000.0 / 60.0 / 60.0 / 24.0;
1412cdf0e10cSrcweir xCal->setDateTime( nDateTime );
1413cdf0e10cSrcweir nDST2 = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
1414cdf0e10cSrcweir nDST2millis = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
1415cdf0e10cSrcweir nDST2InMillis = static_cast<sal_Int32>(nDST2) * 60000 +
1416cdf0e10cSrcweir (nDST2 < 0 ? -1 : 1) * static_cast<sal_uInt16>(nDST2millis);
1417cdf0e10cSrcweir if ( nDST1InMillis != nDST2InMillis )
1418cdf0e10cSrcweir {
1419cdf0e10cSrcweir nDateTime = 0.0 - (double)(nZoneInMillis + nDST2InMillis) / 1000.0 / 60.0 / 60.0 / 24.0;
1420cdf0e10cSrcweir xCal->setDateTime( nDateTime );
1421cdf0e10cSrcweir }
1422cdf0e10cSrcweir nDaySet = xCal->getValue( i18n::CalendarFieldIndex::DAY_OF_MONTH );
1423cdf0e10cSrcweir nMonthSet = xCal->getValue( i18n::CalendarFieldIndex::MONTH );
1424cdf0e10cSrcweir nYearSet = xCal->getValue( i18n::CalendarFieldIndex::YEAR );
1425cdf0e10cSrcweir nHourSet = xCal->getValue( i18n::CalendarFieldIndex::HOUR );
1426cdf0e10cSrcweir nMinuteSet = xCal->getValue( i18n::CalendarFieldIndex::MINUTE );
1427cdf0e10cSrcweir nSecondSet = xCal->getValue( i18n::CalendarFieldIndex::SECOND );
1428cdf0e10cSrcweir nZO = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET );
1429cdf0e10cSrcweir nZOmillis = xCal->getValue( i18n::CalendarFieldIndex::ZONE_OFFSET_SECOND_MILLIS );
1430cdf0e10cSrcweir nDST = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET );
1431cdf0e10cSrcweir nDSTmillis = xCal->getValue( i18n::CalendarFieldIndex::DST_OFFSET_SECOND_MILLIS );
1432cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::DAY_OF_MONTH, nDaySet );
1433cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::MONTH, nMonthSet );
1434cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::YEAR, nYearSet );
1435cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::HOUR, nHourSet );
1436cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::MINUTE, nMinuteSet );
1437cdf0e10cSrcweir xCal->setValue( i18n::CalendarFieldIndex::SECOND, nSecondSet );
1438cdf0e10cSrcweir bValid = xCal->isValid();
1439cdf0e10cSrcweir nDay = xCal->getValue( i18n::CalendarFieldIndex::DAY_OF_MONTH );
1440cdf0e10cSrcweir nMyMonth= xCal->getValue( i18n::CalendarFieldIndex::MONTH );
1441cdf0e10cSrcweir nYear = xCal->getValue( i18n::CalendarFieldIndex::YEAR );
1442cdf0e10cSrcweir nHour = xCal->getValue( i18n::CalendarFieldIndex::HOUR );
1443cdf0e10cSrcweir nMinute = xCal->getValue( i18n::CalendarFieldIndex::MINUTE );
1444cdf0e10cSrcweir nSecond = xCal->getValue( i18n::CalendarFieldIndex::SECOND );
1445cdf0e10cSrcweir bValid = bValid && nDay == nDaySet && nMyMonth == nMonthSet && nYear ==
1446cdf0e10cSrcweir nYearSet && nHour == nHourSet && nMinute == nMinuteSet && nSecond
1447cdf0e10cSrcweir == nSecondSet;
1448cdf0e10cSrcweir }
1449cdf0e10cSrcweir }
1450cdf0e10cSrcweir #endif // NF_TEST_CALENDAR
1451cdf0e10cSrcweir
1452cdf0e10cSrcweir }
1453cdf0e10cSrcweir
1454cdf0e10cSrcweir return res;
1455cdf0e10cSrcweir }
1456cdf0e10cSrcweir
1457cdf0e10cSrcweir
1458cdf0e10cSrcweir //---------------------------------------------------------------------------
1459cdf0e10cSrcweir // ScanStartString
1460cdf0e10cSrcweir //
1461c71adef7SDamjan Jovanovic // Analyze the beginning of the string
1462c71adef7SDamjan Jovanovic // Everything gone => sal_True
1463c71adef7SDamjan Jovanovic // else => sal_False
1464cdf0e10cSrcweir
ScanStartString(const String & rString,const SvNumberformat * pFormat)1465cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::ScanStartString( const String& rString,
1466cdf0e10cSrcweir const SvNumberformat* pFormat )
1467cdf0e10cSrcweir {
1468cdf0e10cSrcweir xub_StrLen nPos = 0;
1469cdf0e10cSrcweir int nDayOfWeek;
1470cdf0e10cSrcweir
1471cdf0e10cSrcweir // First of all, eat leading blanks
1472cdf0e10cSrcweir SkipBlanks(rString, nPos);
1473cdf0e10cSrcweir
1474cdf0e10cSrcweir // Yes, nMatchedAllStrings should know about the sign position
1475cdf0e10cSrcweir nSign = GetSign(rString, nPos);
1476cdf0e10cSrcweir if ( nSign ) // sign?
1477cdf0e10cSrcweir SkipBlanks(rString, nPos);
1478cdf0e10cSrcweir
1479cdf0e10cSrcweir // #102371# match against format string only if start string is not a sign character
1480cdf0e10cSrcweir if ( nMatchedAllStrings && !(nSign && rString.Len() == 1) )
1481cdf0e10cSrcweir { // Match against format in any case, so later on for a "x1-2-3" input
1482cdf0e10cSrcweir // we may distinguish between a xy-m-d (or similar) date and a x0-0-0
1483cdf0e10cSrcweir // format. No sign detection here!
1484cdf0e10cSrcweir if ( ScanStringNumFor( rString, nPos, pFormat, 0, sal_True ) )
1485cdf0e10cSrcweir nMatchedAllStrings |= nMatchedStartString;
1486cdf0e10cSrcweir else
1487cdf0e10cSrcweir nMatchedAllStrings = 0;
1488cdf0e10cSrcweir }
1489cdf0e10cSrcweir
1490cdf0e10cSrcweir if ( GetDecSep(rString, nPos) ) // decimal separator in start string
1491cdf0e10cSrcweir {
1492cdf0e10cSrcweir nDecPos = 1;
1493cdf0e10cSrcweir SkipBlanks(rString, nPos);
1494cdf0e10cSrcweir }
1495cdf0e10cSrcweir else if ( GetCurrency(rString, nPos, pFormat) ) // currency (DM 1)?
1496cdf0e10cSrcweir {
1497cdf0e10cSrcweir eScannedType = NUMBERFORMAT_CURRENCY; // !!! it IS currency !!!
1498cdf0e10cSrcweir SkipBlanks(rString, nPos);
1499cdf0e10cSrcweir if (nSign == 0) // no sign yet
1500cdf0e10cSrcweir {
1501cdf0e10cSrcweir nSign = GetSign(rString, nPos);
1502cdf0e10cSrcweir if ( nSign ) // DM -1
1503cdf0e10cSrcweir SkipBlanks(rString, nPos);
1504cdf0e10cSrcweir }
1505*dab0a4eaSDamjan Jovanovic if ( GetDecSep(rString, nPos) )
1506*dab0a4eaSDamjan Jovanovic {
1507*dab0a4eaSDamjan Jovanovic nDecPos = 1;
1508*dab0a4eaSDamjan Jovanovic SkipBlanks(rString, nPos);
1509*dab0a4eaSDamjan Jovanovic }
1510cdf0e10cSrcweir }
1511cdf0e10cSrcweir else
1512cdf0e10cSrcweir {
1513cdf0e10cSrcweir nMonth = GetMonth(rString, nPos);
1514cdf0e10cSrcweir if ( nMonth ) // month (Jan 1)?
1515cdf0e10cSrcweir {
1516cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date !!!
1517cdf0e10cSrcweir nMonthPos = 1; // month at the beginning
1518cdf0e10cSrcweir if ( nMonth < 0 )
1519cdf0e10cSrcweir SkipChar( '.', rString, nPos ); // abbreviated
1520cdf0e10cSrcweir SkipBlanks(rString, nPos);
1521cdf0e10cSrcweir }
1522cdf0e10cSrcweir else
1523cdf0e10cSrcweir {
1524cdf0e10cSrcweir nDayOfWeek = GetDayOfWeek( rString, nPos );
1525cdf0e10cSrcweir if ( nDayOfWeek )
1526cdf0e10cSrcweir { // day of week is just parsed away
1527cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date !!!
1528cdf0e10cSrcweir if ( nPos < rString.Len() )
1529cdf0e10cSrcweir {
1530cdf0e10cSrcweir if ( nDayOfWeek < 0 )
1531cdf0e10cSrcweir { // abbreviated
1532cdf0e10cSrcweir if ( rString.GetChar( nPos ) == '.' )
1533cdf0e10cSrcweir ++nPos;
1534cdf0e10cSrcweir }
1535cdf0e10cSrcweir else
1536cdf0e10cSrcweir { // full long name
1537cdf0e10cSrcweir SkipBlanks(rString, nPos);
1538cdf0e10cSrcweir SkipString( pFormatter->GetLocaleData()->getLongDateDayOfWeekSep(), rString, nPos );
1539cdf0e10cSrcweir }
1540cdf0e10cSrcweir SkipBlanks(rString, nPos);
1541cdf0e10cSrcweir nMonth = GetMonth(rString, nPos);
1542cdf0e10cSrcweir if ( nMonth ) // month (Jan 1)?
1543cdf0e10cSrcweir {
1544cdf0e10cSrcweir nMonthPos = 1; // month a the beginning
1545cdf0e10cSrcweir if ( nMonth < 0 )
1546cdf0e10cSrcweir SkipChar( '.', rString, nPos ); // abbreviated
1547cdf0e10cSrcweir SkipBlanks(rString, nPos);
1548cdf0e10cSrcweir }
1549cdf0e10cSrcweir }
1550cdf0e10cSrcweir }
1551cdf0e10cSrcweir }
1552cdf0e10cSrcweir }
1553cdf0e10cSrcweir
1554cdf0e10cSrcweir if (nPos < rString.Len()) // not everything consumed
1555cdf0e10cSrcweir {
1556cdf0e10cSrcweir // Does input StartString equal StartString of format?
1557cdf0e10cSrcweir // This time with sign detection!
1558cdf0e10cSrcweir if ( !ScanStringNumFor( rString, nPos, pFormat, 0 ) )
1559cdf0e10cSrcweir return MatchedReturn();
1560cdf0e10cSrcweir }
1561cdf0e10cSrcweir
1562cdf0e10cSrcweir return sal_True;
1563cdf0e10cSrcweir }
1564cdf0e10cSrcweir
1565cdf0e10cSrcweir
1566cdf0e10cSrcweir //---------------------------------------------------------------------------
1567cdf0e10cSrcweir // ScanMidString
1568cdf0e10cSrcweir //
1569c71adef7SDamjan Jovanovic // Analyze the middle of the string
1570c71adef7SDamjan Jovanovic // Everything gone => sal_True
1571c71adef7SDamjan Jovanovic // else => sal_False
1572cdf0e10cSrcweir
ScanMidString(const String & rString,sal_uInt16 nStringPos,const SvNumberformat * pFormat)1573cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::ScanMidString( const String& rString,
1574cdf0e10cSrcweir sal_uInt16 nStringPos, const SvNumberformat* pFormat )
1575cdf0e10cSrcweir {
1576cdf0e10cSrcweir xub_StrLen nPos = 0;
1577cdf0e10cSrcweir short eOldScannedType = eScannedType;
1578cdf0e10cSrcweir
1579cdf0e10cSrcweir if ( nMatchedAllStrings )
1580cdf0e10cSrcweir { // Match against format in any case, so later on for a "1-2-3-4" input
1581cdf0e10cSrcweir // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0
1582cdf0e10cSrcweir // format.
1583cdf0e10cSrcweir if ( ScanStringNumFor( rString, 0, pFormat, nStringPos ) )
1584cdf0e10cSrcweir nMatchedAllStrings |= nMatchedMidString;
1585cdf0e10cSrcweir else
1586cdf0e10cSrcweir nMatchedAllStrings = 0;
1587cdf0e10cSrcweir }
1588cdf0e10cSrcweir
1589cdf0e10cSrcweir SkipBlanks(rString, nPos);
1590cdf0e10cSrcweir if (GetDecSep(rString, nPos)) // decimal separator?
1591cdf0e10cSrcweir {
1592cdf0e10cSrcweir if (nDecPos == 1 || nDecPos == 3) // .12.4 or 1.E2.1
1593cdf0e10cSrcweir return MatchedReturn();
1594cdf0e10cSrcweir else if (nDecPos == 2) // . dup: 12.4.
1595cdf0e10cSrcweir {
1596cdf0e10cSrcweir if (bDecSepInDateSeps) // . also date separator
1597cdf0e10cSrcweir {
1598cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED &&
1599cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATE &&
1600cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATETIME) // already another type
1601cdf0e10cSrcweir return MatchedReturn();
1602cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_UNDEFINED)
1603cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date
1604cdf0e10cSrcweir SkipBlanks(rString, nPos);
1605cdf0e10cSrcweir }
1606cdf0e10cSrcweir else
1607cdf0e10cSrcweir return MatchedReturn();
1608cdf0e10cSrcweir }
1609cdf0e10cSrcweir else
1610cdf0e10cSrcweir {
1611cdf0e10cSrcweir nDecPos = 2; // . in mid string
1612cdf0e10cSrcweir SkipBlanks(rString, nPos);
1613cdf0e10cSrcweir }
1614cdf0e10cSrcweir }
1615cdf0e10cSrcweir else if ( ((eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME)
1616cdf0e10cSrcweir && GetTime100SecSep( rString, nPos ) )
1617cdf0e10cSrcweir { // hundredth seconds separator
1618cdf0e10cSrcweir if ( nDecPos )
1619cdf0e10cSrcweir return MatchedReturn();
1620cdf0e10cSrcweir nDecPos = 2; // . in mid string
1621cdf0e10cSrcweir SkipBlanks(rString, nPos);
1622cdf0e10cSrcweir }
1623cdf0e10cSrcweir
1624cdf0e10cSrcweir if (SkipChar('/', rString, nPos)) // fraction?
1625cdf0e10cSrcweir {
1626cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
1627cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_DATE) // except date
1628cdf0e10cSrcweir return MatchedReturn(); // => jan/31/1994
1629cdf0e10cSrcweir else if ( eScannedType != NUMBERFORMAT_DATE // analyzed date until now
1630cdf0e10cSrcweir && ( eSetType == NUMBERFORMAT_FRACTION // and preset was fraction
1631cdf0e10cSrcweir || (nAnzNums == 3 // or 3 numbers
1632cdf0e10cSrcweir && nStringPos > 2) ) ) // and what ???
1633cdf0e10cSrcweir {
1634cdf0e10cSrcweir SkipBlanks(rString, nPos);
1635cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION; // !!! it IS a fraction
1636cdf0e10cSrcweir }
1637cdf0e10cSrcweir else
1638cdf0e10cSrcweir nPos--; // put '/' back
1639cdf0e10cSrcweir }
1640cdf0e10cSrcweir
1641cdf0e10cSrcweir if (GetThousandSep(rString, nPos, nStringPos)) // 1,000
1642cdf0e10cSrcweir {
1643cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
1644cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_CURRENCY) // except currency
1645cdf0e10cSrcweir return MatchedReturn();
1646cdf0e10cSrcweir nThousand++;
1647cdf0e10cSrcweir }
1648cdf0e10cSrcweir
1649cdf0e10cSrcweir const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1650cdf0e10cSrcweir const String& rDate = pFormatter->GetDateSep();
1651cdf0e10cSrcweir const String& rTime = pLoc->getTimeSep();
1652cdf0e10cSrcweir sal_Unicode cTime = rTime.GetChar(0);
1653cdf0e10cSrcweir SkipBlanks(rString, nPos);
1654cdf0e10cSrcweir if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
1655cdf0e10cSrcweir || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
1656cdf0e10cSrcweir || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
1657cdf0e10cSrcweir || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
1658cdf0e10cSrcweir {
1659cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
1660cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_DATE) // except date
1661cdf0e10cSrcweir return MatchedReturn();
1662cdf0e10cSrcweir SkipBlanks(rString, nPos);
1663cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date
1664cdf0e10cSrcweir short nTmpMonth = GetMonth(rString, nPos); // 10. Jan 94
1665cdf0e10cSrcweir if (nMonth && nTmpMonth) // month dup
1666cdf0e10cSrcweir return MatchedReturn();
1667cdf0e10cSrcweir if (nTmpMonth)
1668cdf0e10cSrcweir {
1669cdf0e10cSrcweir nMonth = nTmpMonth;
1670cdf0e10cSrcweir nMonthPos = 2; // month in the middle
1671cdf0e10cSrcweir if ( nMonth < 0 && SkipChar( '.', rString, nPos ) )
1672cdf0e10cSrcweir ; // short month may be abbreviated Jan.
1673cdf0e10cSrcweir else if ( SkipChar( '-', rString, nPos ) )
1674cdf0e10cSrcweir ; // #79632# recognize 17-Jan-2001 to be a date
1675cdf0e10cSrcweir // #99065# short and long month name
1676cdf0e10cSrcweir else
1677cdf0e10cSrcweir SkipString( pLoc->getLongDateMonthSep(), rString, nPos );
1678cdf0e10cSrcweir SkipBlanks(rString, nPos);
1679cdf0e10cSrcweir }
1680cdf0e10cSrcweir }
1681cdf0e10cSrcweir
1682cdf0e10cSrcweir short nTempMonth = GetMonth(rString, nPos); // month in the middle (10 Jan 94)
1683cdf0e10cSrcweir if (nTempMonth)
1684cdf0e10cSrcweir {
1685cdf0e10cSrcweir if (nMonth != 0) // month dup
1686cdf0e10cSrcweir return MatchedReturn();
1687cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
1688cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_DATE) // except date
1689cdf0e10cSrcweir return MatchedReturn();
1690cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date
1691cdf0e10cSrcweir nMonth = nTempMonth;
1692cdf0e10cSrcweir nMonthPos = 2; // month in the middle
1693cdf0e10cSrcweir if ( nMonth < 0 )
1694cdf0e10cSrcweir SkipChar( '.', rString, nPos ); // abbreviated
1695cdf0e10cSrcweir SkipString( pLoc->getLongDateMonthSep(), rString, nPos );
1696cdf0e10cSrcweir SkipBlanks(rString, nPos);
1697cdf0e10cSrcweir }
1698cdf0e10cSrcweir
1699cdf0e10cSrcweir if ( SkipChar('E', rString, nPos) // 10E, 10e, 10,Ee
1700cdf0e10cSrcweir || SkipChar('e', rString, nPos) )
1701cdf0e10cSrcweir {
1702cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type
1703cdf0e10cSrcweir return MatchedReturn();
1704cdf0e10cSrcweir else
1705cdf0e10cSrcweir {
1706cdf0e10cSrcweir SkipBlanks(rString, nPos);
1707cdf0e10cSrcweir eScannedType = NUMBERFORMAT_SCIENTIFIC; // !!! it IS scientific
1708cdf0e10cSrcweir if ( nThousand+2 == nAnzNums // special case 1.E2
1709cdf0e10cSrcweir && nDecPos == 2 )
1710cdf0e10cSrcweir nDecPos = 3; // 1,100.E2 1,100,100.E3
1711cdf0e10cSrcweir }
1712cdf0e10cSrcweir nESign = GetESign(rString, nPos); // signed exponent?
1713cdf0e10cSrcweir SkipBlanks(rString, nPos);
1714cdf0e10cSrcweir }
1715cdf0e10cSrcweir
1716cdf0e10cSrcweir if ( SkipString(rTime, rString, nPos) ) // time separator?
1717cdf0e10cSrcweir {
1718cdf0e10cSrcweir if (nDecPos) // already . => maybe error
1719cdf0e10cSrcweir {
1720cdf0e10cSrcweir if (bDecSepInDateSeps) // . also date sep
1721cdf0e10cSrcweir {
1722cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_DATE && // already another type than date
1723cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATETIME) // or date time
1724cdf0e10cSrcweir return MatchedReturn();
1725cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_DATE)
1726cdf0e10cSrcweir nDecPos = 0; // reset for time transition
1727cdf0e10cSrcweir }
1728cdf0e10cSrcweir else
1729cdf0e10cSrcweir return MatchedReturn();
1730cdf0e10cSrcweir }
1731cdf0e10cSrcweir if ( ( eScannedType == NUMBERFORMAT_DATE // already date type
1732cdf0e10cSrcweir || eScannedType == NUMBERFORMAT_DATETIME) // or date time
1733cdf0e10cSrcweir && nAnzNums > 3) // and more than 3 numbers? (31.Dez.94 8:23)
1734cdf0e10cSrcweir {
1735cdf0e10cSrcweir SkipBlanks(rString, nPos);
1736cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATETIME; // !!! it IS date with time
1737cdf0e10cSrcweir }
1738cdf0e10cSrcweir else if ( eScannedType != NUMBERFORMAT_UNDEFINED // already another type
1739cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_TIME) // except time
1740cdf0e10cSrcweir return MatchedReturn();
1741cdf0e10cSrcweir else
1742cdf0e10cSrcweir {
1743cdf0e10cSrcweir SkipBlanks(rString, nPos);
1744cdf0e10cSrcweir eScannedType = NUMBERFORMAT_TIME; // !!! it IS a time
1745cdf0e10cSrcweir }
1746cdf0e10cSrcweir if ( !nTimePos )
1747cdf0e10cSrcweir nTimePos = nStringPos + 1;
1748cdf0e10cSrcweir }
1749cdf0e10cSrcweir
1750cdf0e10cSrcweir if (nPos < rString.Len())
1751cdf0e10cSrcweir {
1752cdf0e10cSrcweir switch (eScannedType)
1753cdf0e10cSrcweir {
1754cdf0e10cSrcweir case NUMBERFORMAT_DATE:
1755cdf0e10cSrcweir if (nMonthPos == 1 && pLoc->getLongDateFormat() == MDY)
1756cdf0e10cSrcweir {
1757cdf0e10cSrcweir // #68232# recognize long date separators like ", " in "September 5, 1999"
1758cdf0e10cSrcweir if (SkipString( pLoc->getLongDateDaySep(), rString, nPos ))
1759cdf0e10cSrcweir SkipBlanks( rString, nPos );
1760cdf0e10cSrcweir }
1761cdf0e10cSrcweir else if (nStringPos == 5 && nPos == 0 && rString.Len() == 1 &&
1762cdf0e10cSrcweir rString.GetChar(0) == 'T' && MayBeIso8601())
1763cdf0e10cSrcweir {
1764cdf0e10cSrcweir // ISO 8601 combined date and time, yyyy-mm-ddThh:mm
1765cdf0e10cSrcweir ++nPos;
1766cdf0e10cSrcweir }
1767cdf0e10cSrcweir break;
1768cdf0e10cSrcweir #if NF_RECOGNIZE_ISO8601_TIMEZONES
1769cdf0e10cSrcweir case NUMBERFORMAT_DATETIME:
1770cdf0e10cSrcweir if (nPos == 0 && rString.Len() == 1 && nStringPos >= 9 &&
1771cdf0e10cSrcweir MayBeIso8601())
1772cdf0e10cSrcweir {
1773cdf0e10cSrcweir // ISO 8601 timezone offset
1774cdf0e10cSrcweir switch (rString.GetChar(0))
1775cdf0e10cSrcweir {
1776cdf0e10cSrcweir case '+':
1777cdf0e10cSrcweir case '-':
1778cdf0e10cSrcweir if (nStringPos == nAnzStrings-2 ||
1779cdf0e10cSrcweir nStringPos == nAnzStrings-4)
1780cdf0e10cSrcweir {
1781cdf0e10cSrcweir ++nPos; // yyyy-mm-ddThh:mm[:ss]+xx[[:]yy]
1782cdf0e10cSrcweir // nTimezonePos needed for GetTimeRef()
1783cdf0e10cSrcweir if (!nTimezonePos)
1784cdf0e10cSrcweir nTimezonePos = nStringPos + 1;
1785cdf0e10cSrcweir }
1786cdf0e10cSrcweir break;
1787cdf0e10cSrcweir case ':':
1788cdf0e10cSrcweir if (nTimezonePos && nStringPos >= 11 &&
1789cdf0e10cSrcweir nStringPos == nAnzStrings-2)
1790cdf0e10cSrcweir ++nPos; // yyyy-mm-ddThh:mm[:ss]+xx:yy
1791cdf0e10cSrcweir break;
1792cdf0e10cSrcweir }
1793cdf0e10cSrcweir }
1794cdf0e10cSrcweir break;
1795cdf0e10cSrcweir #endif
1796cdf0e10cSrcweir }
1797cdf0e10cSrcweir }
1798cdf0e10cSrcweir
1799cdf0e10cSrcweir if (nPos < rString.Len()) // not everything consumed?
1800cdf0e10cSrcweir {
1801cdf0e10cSrcweir if ( nMatchedAllStrings & ~nMatchedVirgin )
1802cdf0e10cSrcweir eScannedType = eOldScannedType;
1803cdf0e10cSrcweir else
1804cdf0e10cSrcweir return sal_False;
1805cdf0e10cSrcweir }
1806cdf0e10cSrcweir
1807cdf0e10cSrcweir return sal_True;
1808cdf0e10cSrcweir }
1809cdf0e10cSrcweir
1810cdf0e10cSrcweir
1811cdf0e10cSrcweir //---------------------------------------------------------------------------
1812cdf0e10cSrcweir // ScanEndString
1813cdf0e10cSrcweir //
1814c71adef7SDamjan Jovanovic // Analyze the conclusion
1815c71adef7SDamjan Jovanovic // Everything gone => sal_True
1816c71adef7SDamjan Jovanovic // else => sal_False
1817cdf0e10cSrcweir
ScanEndString(const String & rString,const SvNumberformat * pFormat)1818cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::ScanEndString( const String& rString,
1819cdf0e10cSrcweir const SvNumberformat* pFormat )
1820cdf0e10cSrcweir {
1821cdf0e10cSrcweir xub_StrLen nPos = 0;
1822cdf0e10cSrcweir
1823cdf0e10cSrcweir if ( nMatchedAllStrings )
1824cdf0e10cSrcweir { // Match against format in any case, so later on for a "1-2-3-4" input
1825cdf0e10cSrcweir // we may distinguish between a y-m-d (or similar) date and a 0-0-0-0
1826cdf0e10cSrcweir // format.
1827cdf0e10cSrcweir if ( ScanStringNumFor( rString, 0, pFormat, 0xFFFF ) )
1828cdf0e10cSrcweir nMatchedAllStrings |= nMatchedEndString;
1829cdf0e10cSrcweir else
1830cdf0e10cSrcweir nMatchedAllStrings = 0;
1831cdf0e10cSrcweir }
1832cdf0e10cSrcweir
1833cdf0e10cSrcweir SkipBlanks(rString, nPos);
1834cdf0e10cSrcweir if (GetDecSep(rString, nPos)) // decimal separator?
1835cdf0e10cSrcweir {
1836cdf0e10cSrcweir if (nDecPos == 1 || nDecPos == 3) // .12.4 or 12.E4.
1837cdf0e10cSrcweir return MatchedReturn();
1838cdf0e10cSrcweir else if (nDecPos == 2) // . dup: 12.4.
1839cdf0e10cSrcweir {
1840cdf0e10cSrcweir if (bDecSepInDateSeps) // . also date sep
1841cdf0e10cSrcweir {
1842cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_UNDEFINED &&
1843cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATE &&
1844cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATETIME) // already another type
1845cdf0e10cSrcweir return MatchedReturn();
1846cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_UNDEFINED)
1847cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE; // !!! it IS a date
1848cdf0e10cSrcweir SkipBlanks(rString, nPos);
1849cdf0e10cSrcweir }
1850cdf0e10cSrcweir else
1851cdf0e10cSrcweir return MatchedReturn();
1852cdf0e10cSrcweir }
1853cdf0e10cSrcweir else
1854cdf0e10cSrcweir {
1855cdf0e10cSrcweir nDecPos = 3; // . in end string
1856cdf0e10cSrcweir SkipBlanks(rString, nPos);
1857cdf0e10cSrcweir }
1858cdf0e10cSrcweir }
1859cdf0e10cSrcweir
1860cdf0e10cSrcweir if ( nSign == 0 // conflict - not signed
1861cdf0e10cSrcweir && eScannedType != NUMBERFORMAT_DATE) // and not date
1862cdf0e10cSrcweir //!? catch time too?
1863cdf0e10cSrcweir { // not signed yet
1864cdf0e10cSrcweir nSign = GetSign(rString, nPos); // 1- DM
1865cdf0e10cSrcweir if (nNegCheck) // '(' as sign
1866cdf0e10cSrcweir return MatchedReturn();
1867cdf0e10cSrcweir }
1868cdf0e10cSrcweir
1869cdf0e10cSrcweir SkipBlanks(rString, nPos);
1870cdf0e10cSrcweir if (nNegCheck && SkipChar(')', rString, nPos)) // skip ')' if appropriate
1871cdf0e10cSrcweir {
1872cdf0e10cSrcweir nNegCheck = 0;
1873cdf0e10cSrcweir SkipBlanks(rString, nPos);
1874cdf0e10cSrcweir }
1875cdf0e10cSrcweir
1876cdf0e10cSrcweir if ( GetCurrency(rString, nPos, pFormat) ) // currency symbol?
1877cdf0e10cSrcweir {
1878cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED) // currency dup
1879cdf0e10cSrcweir return MatchedReturn();
1880cdf0e10cSrcweir else
1881cdf0e10cSrcweir {
1882cdf0e10cSrcweir SkipBlanks(rString, nPos);
1883cdf0e10cSrcweir eScannedType = NUMBERFORMAT_CURRENCY;
1884cdf0e10cSrcweir } // behind currency a '-' is allowed
1885cdf0e10cSrcweir if (nSign == 0) // not signed yet
1886cdf0e10cSrcweir {
1887cdf0e10cSrcweir nSign = GetSign(rString, nPos); // DM -
1888cdf0e10cSrcweir SkipBlanks(rString, nPos);
1889cdf0e10cSrcweir if (nNegCheck) // 3 DM (
1890cdf0e10cSrcweir return MatchedReturn();
1891cdf0e10cSrcweir }
1892cdf0e10cSrcweir if ( nNegCheck && eScannedType == NUMBERFORMAT_CURRENCY
1893cdf0e10cSrcweir && SkipChar(')', rString, nPos) )
1894cdf0e10cSrcweir {
1895cdf0e10cSrcweir nNegCheck = 0; // ')' skipped
1896cdf0e10cSrcweir SkipBlanks(rString, nPos); // only if currency
1897cdf0e10cSrcweir }
1898cdf0e10cSrcweir }
1899cdf0e10cSrcweir
1900cdf0e10cSrcweir if ( SkipChar('%', rString, nPos) ) // 1 %
1901cdf0e10cSrcweir {
1902cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED) // already another type
1903cdf0e10cSrcweir return MatchedReturn();
1904cdf0e10cSrcweir SkipBlanks(rString, nPos);
1905cdf0e10cSrcweir eScannedType = NUMBERFORMAT_PERCENT;
1906cdf0e10cSrcweir }
1907cdf0e10cSrcweir
1908cdf0e10cSrcweir const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData();
1909cdf0e10cSrcweir const String& rDate = pFormatter->GetDateSep();
1910cdf0e10cSrcweir const String& rTime = pLoc->getTimeSep();
1911cdf0e10cSrcweir if ( SkipString(rTime, rString, nPos) ) // 10:
1912cdf0e10cSrcweir {
1913cdf0e10cSrcweir if (nDecPos) // already , => error
1914cdf0e10cSrcweir return MatchedReturn();
1915cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_DATE && nAnzNums > 2) // 31.Dez.94 8:
1916cdf0e10cSrcweir {
1917cdf0e10cSrcweir SkipBlanks(rString, nPos);
1918cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATETIME;
1919cdf0e10cSrcweir }
1920cdf0e10cSrcweir else if (eScannedType != NUMBERFORMAT_UNDEFINED &&
1921cdf0e10cSrcweir eScannedType != NUMBERFORMAT_TIME) // already another type
1922cdf0e10cSrcweir return MatchedReturn();
1923cdf0e10cSrcweir else
1924cdf0e10cSrcweir {
1925cdf0e10cSrcweir SkipBlanks(rString, nPos);
1926cdf0e10cSrcweir eScannedType = NUMBERFORMAT_TIME;
1927cdf0e10cSrcweir }
1928cdf0e10cSrcweir if ( !nTimePos )
1929cdf0e10cSrcweir nTimePos = nAnzStrings;
1930cdf0e10cSrcweir }
1931cdf0e10cSrcweir
1932cdf0e10cSrcweir sal_Unicode cTime = rTime.GetChar(0);
1933cdf0e10cSrcweir if ( SkipString(rDate, rString, nPos) // 10., 10-, 10/
1934cdf0e10cSrcweir || ((cTime != '.') && SkipChar('.', rString, nPos)) // TRICKY:
1935cdf0e10cSrcweir || ((cTime != '/') && SkipChar('/', rString, nPos)) // short boolean
1936cdf0e10cSrcweir || ((cTime != '-') && SkipChar('-', rString, nPos)) ) // evaluation!
1937cdf0e10cSrcweir {
1938cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED &&
1939cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATE) // already another type
1940cdf0e10cSrcweir return MatchedReturn();
1941cdf0e10cSrcweir else
1942cdf0e10cSrcweir {
1943cdf0e10cSrcweir SkipBlanks(rString, nPos);
1944cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE;
1945cdf0e10cSrcweir }
1946cdf0e10cSrcweir short nTmpMonth = GetMonth(rString, nPos); // 10. Jan
1947cdf0e10cSrcweir if (nMonth && nTmpMonth) // month dup
1948cdf0e10cSrcweir return MatchedReturn();
1949cdf0e10cSrcweir if (nTmpMonth)
1950cdf0e10cSrcweir {
1951cdf0e10cSrcweir nMonth = nTmpMonth;
1952cdf0e10cSrcweir nMonthPos = 3; // month at end
1953cdf0e10cSrcweir if ( nMonth < 0 )
1954cdf0e10cSrcweir SkipChar( '.', rString, nPos ); // abbreviated
1955cdf0e10cSrcweir SkipBlanks(rString, nPos);
1956cdf0e10cSrcweir }
1957cdf0e10cSrcweir }
1958cdf0e10cSrcweir
1959cdf0e10cSrcweir short nTempMonth = GetMonth(rString, nPos); // 10 Jan
1960cdf0e10cSrcweir if (nTempMonth)
1961cdf0e10cSrcweir {
1962cdf0e10cSrcweir if (nMonth) // month dup
1963cdf0e10cSrcweir return MatchedReturn();
1964cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED &&
1965cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATE) // already another type
1966cdf0e10cSrcweir return MatchedReturn();
1967cdf0e10cSrcweir eScannedType = NUMBERFORMAT_DATE;
1968cdf0e10cSrcweir nMonth = nTempMonth;
1969cdf0e10cSrcweir nMonthPos = 3; // month at end
1970cdf0e10cSrcweir if ( nMonth < 0 )
1971cdf0e10cSrcweir SkipChar( '.', rString, nPos ); // abbreviated
1972cdf0e10cSrcweir SkipBlanks(rString, nPos);
1973cdf0e10cSrcweir }
1974cdf0e10cSrcweir
1975cdf0e10cSrcweir xub_StrLen nOrigPos = nPos;
1976cdf0e10cSrcweir if (GetTimeAmPm(rString, nPos))
1977cdf0e10cSrcweir {
1978cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_UNDEFINED &&
1979cdf0e10cSrcweir eScannedType != NUMBERFORMAT_TIME &&
1980cdf0e10cSrcweir eScannedType != NUMBERFORMAT_DATETIME) // already another type
1981cdf0e10cSrcweir return MatchedReturn();
1982cdf0e10cSrcweir else
1983cdf0e10cSrcweir {
1984cdf0e10cSrcweir // If not already scanned as time, 6.78am does not result in 6
1985cdf0e10cSrcweir // seconds and 78 hundredths in the morning. Keep as suffix.
1986cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_TIME && nDecPos == 2 && nAnzNums == 2)
1987cdf0e10cSrcweir nPos = nOrigPos; // rewind am/pm
1988cdf0e10cSrcweir else
1989cdf0e10cSrcweir {
1990cdf0e10cSrcweir SkipBlanks(rString, nPos);
1991cdf0e10cSrcweir if ( eScannedType != NUMBERFORMAT_DATETIME )
1992cdf0e10cSrcweir eScannedType = NUMBERFORMAT_TIME;
1993cdf0e10cSrcweir }
1994cdf0e10cSrcweir }
1995cdf0e10cSrcweir }
1996cdf0e10cSrcweir
1997cdf0e10cSrcweir if ( nNegCheck && SkipChar(')', rString, nPos) )
1998cdf0e10cSrcweir {
1999cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_CURRENCY) // only if currency
2000cdf0e10cSrcweir {
2001cdf0e10cSrcweir nNegCheck = 0; // skip ')'
2002cdf0e10cSrcweir SkipBlanks(rString, nPos);
2003cdf0e10cSrcweir }
2004cdf0e10cSrcweir else
2005cdf0e10cSrcweir return MatchedReturn();
2006cdf0e10cSrcweir }
2007cdf0e10cSrcweir
2008cdf0e10cSrcweir if ( nPos < rString.Len() &&
2009cdf0e10cSrcweir (eScannedType == NUMBERFORMAT_DATE
2010cdf0e10cSrcweir || eScannedType == NUMBERFORMAT_DATETIME) )
2011cdf0e10cSrcweir { // day of week is just parsed away
2012cdf0e10cSrcweir xub_StrLen nOldPos = nPos;
2013cdf0e10cSrcweir const String& rSep = pFormatter->GetLocaleData()->getLongDateDayOfWeekSep();
2014cdf0e10cSrcweir if ( StringContains( rSep, rString, nPos ) )
2015cdf0e10cSrcweir {
2016cdf0e10cSrcweir nPos = nPos + rSep.Len();
2017cdf0e10cSrcweir SkipBlanks(rString, nPos);
2018cdf0e10cSrcweir }
2019cdf0e10cSrcweir int nDayOfWeek = GetDayOfWeek( rString, nPos );
2020cdf0e10cSrcweir if ( nDayOfWeek )
2021cdf0e10cSrcweir {
2022cdf0e10cSrcweir if ( nPos < rString.Len() )
2023cdf0e10cSrcweir {
2024cdf0e10cSrcweir if ( nDayOfWeek < 0 )
2025cdf0e10cSrcweir { // short
2026cdf0e10cSrcweir if ( rString.GetChar( nPos ) == '.' )
2027cdf0e10cSrcweir ++nPos;
2028cdf0e10cSrcweir }
2029cdf0e10cSrcweir SkipBlanks(rString, nPos);
2030cdf0e10cSrcweir }
2031cdf0e10cSrcweir }
2032cdf0e10cSrcweir else
2033cdf0e10cSrcweir nPos = nOldPos;
2034cdf0e10cSrcweir }
2035cdf0e10cSrcweir
2036cdf0e10cSrcweir #if NF_RECOGNIZE_ISO8601_TIMEZONES
2037cdf0e10cSrcweir if (nPos == 0 && eScannedType == NUMBERFORMAT_DATETIME &&
2038cdf0e10cSrcweir rString.Len() == 1 && rString.GetChar(0) == 'Z' && MayBeIso8601())
2039cdf0e10cSrcweir {
2040cdf0e10cSrcweir // ISO 8601 timezone UTC yyyy-mm-ddThh:mmZ
2041cdf0e10cSrcweir ++nPos;
2042cdf0e10cSrcweir }
2043cdf0e10cSrcweir #endif
2044cdf0e10cSrcweir
2045cdf0e10cSrcweir if (nPos < rString.Len()) // everything consumed?
2046cdf0e10cSrcweir {
2047cdf0e10cSrcweir // does input EndString equal EndString in Format?
2048cdf0e10cSrcweir if ( !ScanStringNumFor( rString, nPos, pFormat, 0xFFFF ) )
2049cdf0e10cSrcweir return sal_False;
2050cdf0e10cSrcweir }
2051cdf0e10cSrcweir
2052cdf0e10cSrcweir return sal_True;
2053cdf0e10cSrcweir }
2054cdf0e10cSrcweir
2055cdf0e10cSrcweir
ScanStringNumFor(const String & rString,xub_StrLen nPos,const SvNumberformat * pFormat,sal_uInt16 nString,sal_Bool bDontDetectNegation)2056cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::ScanStringNumFor(
2057cdf0e10cSrcweir const String& rString, // String to scan
2058cdf0e10cSrcweir xub_StrLen nPos, // Position until which was consumed
2059cdf0e10cSrcweir const SvNumberformat* pFormat, // The format to match
2060cdf0e10cSrcweir sal_uInt16 nString, // Substring of format, 0xFFFF => last
2061cdf0e10cSrcweir sal_Bool bDontDetectNegation // Suppress sign detection
2062cdf0e10cSrcweir )
2063cdf0e10cSrcweir {
2064cdf0e10cSrcweir if ( !pFormat )
2065cdf0e10cSrcweir return sal_False;
2066cdf0e10cSrcweir const ::utl::TransliterationWrapper* pTransliteration = pFormatter->GetTransliteration();
2067cdf0e10cSrcweir const String* pStr;
2068cdf0e10cSrcweir String aString( rString );
2069cdf0e10cSrcweir sal_Bool bFound = sal_False;
2070cdf0e10cSrcweir sal_Bool bFirst = sal_True;
2071cdf0e10cSrcweir sal_Bool bContinue = sal_True;
2072cdf0e10cSrcweir sal_uInt16 nSub;
2073cdf0e10cSrcweir do
2074cdf0e10cSrcweir {
2075cdf0e10cSrcweir // Don't try "lower" subformats ff the very first match was the second
2076cdf0e10cSrcweir // or third subformat.
2077cdf0e10cSrcweir nSub = nStringScanNumFor;
2078cdf0e10cSrcweir do
2079cdf0e10cSrcweir { // Step through subformats, first positive, then negative, then
2080cdf0e10cSrcweir // other, but not the last (text) subformat.
2081cdf0e10cSrcweir pStr = pFormat->GetNumForString( nSub, nString, sal_True );
2082cdf0e10cSrcweir if ( pStr && pTransliteration->isEqual( aString, *pStr ) )
2083cdf0e10cSrcweir {
2084cdf0e10cSrcweir bFound = sal_True;
2085cdf0e10cSrcweir bContinue = sal_False;
2086cdf0e10cSrcweir }
2087cdf0e10cSrcweir else if ( nSub < 2 )
2088cdf0e10cSrcweir ++nSub;
2089cdf0e10cSrcweir else
2090cdf0e10cSrcweir bContinue = sal_False;
2091cdf0e10cSrcweir } while ( bContinue );
2092cdf0e10cSrcweir if ( !bFound && bFirst && nPos )
2093cdf0e10cSrcweir { // try remaining substring
2094cdf0e10cSrcweir bFirst = sal_False;
2095cdf0e10cSrcweir aString.Erase( 0, nPos );
2096cdf0e10cSrcweir bContinue = sal_True;
2097cdf0e10cSrcweir }
2098cdf0e10cSrcweir } while ( bContinue );
2099cdf0e10cSrcweir
2100cdf0e10cSrcweir if ( !bFound )
2101cdf0e10cSrcweir {
2102cdf0e10cSrcweir if ( !bDontDetectNegation && (nString == 0) && !bFirst && (nSign < 0)
2103cdf0e10cSrcweir && pFormat->IsNegativeRealNegative() )
2104cdf0e10cSrcweir { // simply negated twice? --1
2105cdf0e10cSrcweir aString.EraseAllChars( ' ' );
2106cdf0e10cSrcweir if ( (aString.Len() == 1) && (aString.GetChar(0) == '-') )
2107cdf0e10cSrcweir {
2108cdf0e10cSrcweir bFound = sal_True;
2109cdf0e10cSrcweir nStringScanSign = -1;
2110cdf0e10cSrcweir nSub = 0; //! not 1
2111cdf0e10cSrcweir }
2112cdf0e10cSrcweir }
2113cdf0e10cSrcweir if ( !bFound )
2114cdf0e10cSrcweir return sal_False;
2115cdf0e10cSrcweir }
2116cdf0e10cSrcweir else if ( !bDontDetectNegation && (nSub == 1) &&
2117cdf0e10cSrcweir pFormat->IsNegativeRealNegative() )
2118cdf0e10cSrcweir { // negative
2119cdf0e10cSrcweir if ( nStringScanSign < 0 )
2120cdf0e10cSrcweir {
2121cdf0e10cSrcweir if ( (nSign < 0) && (nStringScanNumFor != 1) )
2122cdf0e10cSrcweir nStringScanSign = 1; // triple negated --1 yyy
2123cdf0e10cSrcweir }
2124cdf0e10cSrcweir else if ( nStringScanSign == 0 )
2125cdf0e10cSrcweir {
2126cdf0e10cSrcweir if ( nSign < 0 )
2127cdf0e10cSrcweir { // nSign and nStringScanSign will be combined later,
2128cdf0e10cSrcweir // flip sign if doubly negated
2129cdf0e10cSrcweir if ( (nString == 0) && !bFirst
2130cdf0e10cSrcweir && SvNumberformat::HasStringNegativeSign( aString ) )
2131cdf0e10cSrcweir nStringScanSign = -1; // direct double negation
2132cdf0e10cSrcweir else if ( pFormat->IsNegativeWithoutSign() )
2133cdf0e10cSrcweir nStringScanSign = -1; // indirect double negation
2134cdf0e10cSrcweir }
2135cdf0e10cSrcweir else
2136cdf0e10cSrcweir nStringScanSign = -1;
2137cdf0e10cSrcweir }
2138cdf0e10cSrcweir else // > 0
2139cdf0e10cSrcweir nStringScanSign = -1;
2140cdf0e10cSrcweir }
2141cdf0e10cSrcweir nStringScanNumFor = nSub;
2142cdf0e10cSrcweir return sal_True;
2143cdf0e10cSrcweir }
2144cdf0e10cSrcweir
2145cdf0e10cSrcweir
2146cdf0e10cSrcweir //---------------------------------------------------------------------------
2147cdf0e10cSrcweir // IsNumberFormatMain
2148cdf0e10cSrcweir //
2149cdf0e10cSrcweir // Recognizes types of number, exponential, fraction, percent, currency, date, time.
2150cdf0e10cSrcweir // Else text => return sal_False
2151cdf0e10cSrcweir
IsNumberFormatMain(const String & rString,double &,const SvNumberformat * pFormat)2152cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::IsNumberFormatMain(
2153cdf0e10cSrcweir const String& rString, // string to be analyzed
2154cdf0e10cSrcweir double& , // OUT: result as number, if possible
2155cdf0e10cSrcweir const SvNumberformat* pFormat ) // maybe number format set to match against
2156cdf0e10cSrcweir {
2157cdf0e10cSrcweir Reset();
2158cdf0e10cSrcweir NumberStringDivision( rString ); // breakdown into strings and numbers
2159cdf0e10cSrcweir if (nAnzStrings >= SV_MAX_ANZ_INPUT_STRINGS) // too many elements
2160cdf0e10cSrcweir return sal_False; // Njet, Nope, ...
2161cdf0e10cSrcweir
2162cdf0e10cSrcweir if (nAnzNums == 0) // no number in input
2163cdf0e10cSrcweir {
2164cdf0e10cSrcweir if ( nAnzStrings > 0 )
2165cdf0e10cSrcweir {
2166cdf0e10cSrcweir // Here we may change the original, we don't need it anymore.
2167cdf0e10cSrcweir // This saves copies and ToUpper() in GetLogical() and is faster.
2168cdf0e10cSrcweir String& rStrArray = sStrArray[0];
2169cdf0e10cSrcweir rStrArray.EraseTrailingChars( ' ' );
2170cdf0e10cSrcweir rStrArray.EraseLeadingChars( ' ' );
2171cdf0e10cSrcweir nLogical = GetLogical( rStrArray );
2172cdf0e10cSrcweir if ( nLogical )
2173cdf0e10cSrcweir {
2174cdf0e10cSrcweir eScannedType = NUMBERFORMAT_LOGICAL; // !!! it's a BOOLEAN
2175cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2176cdf0e10cSrcweir return sal_True;
2177cdf0e10cSrcweir }
2178cdf0e10cSrcweir else
2179cdf0e10cSrcweir return sal_False; // simple text
2180cdf0e10cSrcweir }
2181cdf0e10cSrcweir else
2182cdf0e10cSrcweir return sal_False; // simple text
2183cdf0e10cSrcweir }
2184cdf0e10cSrcweir
2185cdf0e10cSrcweir sal_uInt16 i = 0; // mark any symbol
2186cdf0e10cSrcweir sal_uInt16 j = 0; // mark only numbers
2187cdf0e10cSrcweir
2188cdf0e10cSrcweir switch ( nAnzNums )
2189cdf0e10cSrcweir {
2190cdf0e10cSrcweir case 1 : // Exactly 1 number in input
2191cdf0e10cSrcweir { // nAnzStrings >= 1
2192cdf0e10cSrcweir if (GetNextNumber(i,j)) // i=1,0
2193cdf0e10cSrcweir { // Number at start
2194cdf0e10cSrcweir if (eSetType == NUMBERFORMAT_FRACTION) // Fraction 1 = 1/1
2195cdf0e10cSrcweir {
2196cdf0e10cSrcweir if (i >= nAnzStrings || // no end string nor decimal separator
2197cdf0e10cSrcweir sStrArray[i] == pFormatter->GetNumDecimalSep())
2198cdf0e10cSrcweir {
2199cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION;
2200cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2201cdf0e10cSrcweir return sal_True;
2202cdf0e10cSrcweir }
2203cdf0e10cSrcweir }
2204cdf0e10cSrcweir }
2205cdf0e10cSrcweir else
2206cdf0e10cSrcweir { // Analyze start string
2207cdf0e10cSrcweir if (!ScanStartString( sStrArray[i], pFormat )) // i=0
2208cdf0e10cSrcweir return sal_False; // already an error
2209cdf0e10cSrcweir i++; // next symbol, i=1
2210cdf0e10cSrcweir }
2211cdf0e10cSrcweir GetNextNumber(i,j); // i=1,2
2212cdf0e10cSrcweir if (eSetType == NUMBERFORMAT_FRACTION) // Fraction -1 = -1/1
2213cdf0e10cSrcweir {
2214cdf0e10cSrcweir if (nSign && !nNegCheck && // Sign +, -
2215cdf0e10cSrcweir eScannedType == NUMBERFORMAT_UNDEFINED && // not date or currency
2216cdf0e10cSrcweir nDecPos == 0 && // no previous decimal separator
2217cdf0e10cSrcweir (i >= nAnzStrings || // no end string nor decimal separator
2218cdf0e10cSrcweir sStrArray[i] == pFormatter->GetNumDecimalSep())
2219cdf0e10cSrcweir )
2220cdf0e10cSrcweir {
2221cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION;
2222cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2223cdf0e10cSrcweir return sal_True;
2224cdf0e10cSrcweir }
2225cdf0e10cSrcweir }
2226cdf0e10cSrcweir if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
2227cdf0e10cSrcweir return sal_False;
2228cdf0e10cSrcweir }
2229cdf0e10cSrcweir break;
2230cdf0e10cSrcweir case 2 : // Exactly 2 numbers in input
2231cdf0e10cSrcweir { // nAnzStrings >= 3
2232cdf0e10cSrcweir if (!GetNextNumber(i,j)) // i=1,0
2233cdf0e10cSrcweir { // Analyze start string
2234cdf0e10cSrcweir if (!ScanStartString( sStrArray[i], pFormat ))
2235cdf0e10cSrcweir return sal_False; // already an error
2236cdf0e10cSrcweir i++; // i=1
2237cdf0e10cSrcweir }
2238cdf0e10cSrcweir GetNextNumber(i,j); // i=1,2
2239cdf0e10cSrcweir if ( !ScanMidString( sStrArray[i], i, pFormat ) )
2240cdf0e10cSrcweir return sal_False;
2241cdf0e10cSrcweir i++; // next symbol, i=2,3
2242cdf0e10cSrcweir GetNextNumber(i,j); // i=3,4
2243cdf0e10cSrcweir if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
2244cdf0e10cSrcweir return sal_False;
2245cdf0e10cSrcweir if (eSetType == NUMBERFORMAT_FRACTION) // -1,200. as fraction
2246cdf0e10cSrcweir {
2247cdf0e10cSrcweir if (!nNegCheck && // no sign '('
2248cdf0e10cSrcweir eScannedType == NUMBERFORMAT_UNDEFINED &&
2249cdf0e10cSrcweir (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end
2250cdf0e10cSrcweir )
2251cdf0e10cSrcweir {
2252cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION;
2253cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2254cdf0e10cSrcweir return sal_True;
2255cdf0e10cSrcweir }
2256cdf0e10cSrcweir }
2257cdf0e10cSrcweir }
2258cdf0e10cSrcweir break;
2259cdf0e10cSrcweir case 3 : // Exactly 3 numbers in input
2260cdf0e10cSrcweir { // nAnzStrings >= 5
2261cdf0e10cSrcweir if (!GetNextNumber(i,j)) // i=1,0
2262cdf0e10cSrcweir { // Analyze start string
2263cdf0e10cSrcweir if (!ScanStartString( sStrArray[i], pFormat ))
2264cdf0e10cSrcweir return sal_False; // already an error
2265cdf0e10cSrcweir i++; // i=1
2266cdf0e10cSrcweir if (nDecPos == 1) // decimal separator at start => error
2267cdf0e10cSrcweir return sal_False;
2268cdf0e10cSrcweir }
2269cdf0e10cSrcweir GetNextNumber(i,j); // i=1,2
2270cdf0e10cSrcweir if ( !ScanMidString( sStrArray[i], i, pFormat ) )
2271cdf0e10cSrcweir return sal_False;
2272cdf0e10cSrcweir i++; // i=2,3
2273cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at end
2274cdf0e10cSrcweir return sal_False;
2275cdf0e10cSrcweir GetNextNumber(i,j); // i=3,4
2276cdf0e10cSrcweir if ( !ScanMidString( sStrArray[i], i, pFormat ) )
2277cdf0e10cSrcweir return sal_False;
2278cdf0e10cSrcweir i++; // i=4,5
2279cdf0e10cSrcweir GetNextNumber(i,j); // i=5,6
2280cdf0e10cSrcweir if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
2281cdf0e10cSrcweir return sal_False;
2282cdf0e10cSrcweir if (eSetType == NUMBERFORMAT_FRACTION) // -1,200,100. as fraction
2283cdf0e10cSrcweir {
2284cdf0e10cSrcweir if (!nNegCheck && // no sign '('
2285cdf0e10cSrcweir eScannedType == NUMBERFORMAT_UNDEFINED &&
2286cdf0e10cSrcweir (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end
2287cdf0e10cSrcweir )
2288cdf0e10cSrcweir {
2289cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION;
2290cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2291cdf0e10cSrcweir return sal_True;
2292cdf0e10cSrcweir }
2293cdf0e10cSrcweir }
2294cdf0e10cSrcweir if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos )
2295cdf0e10cSrcweir return sal_False; // #36857# not a real fraction
2296cdf0e10cSrcweir }
2297cdf0e10cSrcweir break;
2298cdf0e10cSrcweir default: // More than 3 numbers in input
2299cdf0e10cSrcweir { // nAnzStrings >= 7
2300cdf0e10cSrcweir if (!GetNextNumber(i,j)) // i=1,0
2301cdf0e10cSrcweir { // Analyze startstring
2302cdf0e10cSrcweir if (!ScanStartString( sStrArray[i], pFormat ))
2303cdf0e10cSrcweir return sal_False; // already an error
2304cdf0e10cSrcweir i++; // i=1
2305cdf0e10cSrcweir if (nDecPos == 1) // decimal separator at start => error
2306cdf0e10cSrcweir return sal_False;
2307cdf0e10cSrcweir }
2308cdf0e10cSrcweir GetNextNumber(i,j); // i=1,2
2309cdf0e10cSrcweir if ( !ScanMidString( sStrArray[i], i, pFormat ) )
2310cdf0e10cSrcweir return sal_False;
2311cdf0e10cSrcweir i++; // i=2,3
2312cdf0e10cSrcweir sal_uInt16 nThOld = 10; // just not 0 or 1
2313cdf0e10cSrcweir while (nThOld != nThousand && j < nAnzNums-1)
2314cdf0e10cSrcweir // Execute at least one time
2315cdf0e10cSrcweir // but leave one number.
2316cdf0e10cSrcweir { // Loop over group separators
2317cdf0e10cSrcweir nThOld = nThousand;
2318cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at end
2319cdf0e10cSrcweir return sal_False;
2320cdf0e10cSrcweir GetNextNumber(i,j);
2321cdf0e10cSrcweir if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) )
2322cdf0e10cSrcweir return sal_False;
2323cdf0e10cSrcweir i++;
2324cdf0e10cSrcweir }
2325cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_DATE || // long date or
2326cdf0e10cSrcweir eScannedType == NUMBERFORMAT_TIME || // long time or
2327cdf0e10cSrcweir eScannedType == NUMBERFORMAT_UNDEFINED) // long number
2328cdf0e10cSrcweir {
2329cdf0e10cSrcweir for (sal_uInt16 k = j; k < nAnzNums-1; k++)
2330cdf0e10cSrcweir {
2331cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_SCIENTIFIC) // E only at endd
2332cdf0e10cSrcweir return sal_False;
2333cdf0e10cSrcweir GetNextNumber(i,j);
2334cdf0e10cSrcweir if ( i < nAnzStrings && !ScanMidString( sStrArray[i], i, pFormat ) )
2335cdf0e10cSrcweir return sal_False;
2336cdf0e10cSrcweir i++;
2337cdf0e10cSrcweir }
2338cdf0e10cSrcweir }
2339cdf0e10cSrcweir GetNextNumber(i,j);
2340cdf0e10cSrcweir if (i < nAnzStrings && !ScanEndString( sStrArray[i], pFormat ))
2341cdf0e10cSrcweir return sal_False;
2342cdf0e10cSrcweir if (eSetType == NUMBERFORMAT_FRACTION) // -1,200,100. as fraction
2343cdf0e10cSrcweir {
2344cdf0e10cSrcweir if (!nNegCheck && // no sign '('
2345cdf0e10cSrcweir eScannedType == NUMBERFORMAT_UNDEFINED &&
2346cdf0e10cSrcweir (nDecPos == 0 || nDecPos == 3) // no decimal separator or at end
2347cdf0e10cSrcweir )
2348cdf0e10cSrcweir {
2349cdf0e10cSrcweir eScannedType = NUMBERFORMAT_FRACTION;
2350cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2351cdf0e10cSrcweir return sal_True;
2352cdf0e10cSrcweir }
2353cdf0e10cSrcweir }
2354cdf0e10cSrcweir if ( eScannedType == NUMBERFORMAT_FRACTION && nDecPos )
2355cdf0e10cSrcweir return sal_False; // #36857# not a real fraction
2356cdf0e10cSrcweir }
2357cdf0e10cSrcweir }
2358cdf0e10cSrcweir
2359cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_UNDEFINED)
2360cdf0e10cSrcweir {
2361cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2362cdf0e10cSrcweir // did match including nMatchedUsedAsReturn
2363cdf0e10cSrcweir sal_Bool bDidMatch = (nMatchedAllStrings != 0);
2364cdf0e10cSrcweir if ( nMatchedAllStrings )
2365cdf0e10cSrcweir {
2366cdf0e10cSrcweir sal_Bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual(
2367cdf0e10cSrcweir nStringScanNumFor, nAnzStrings, nAnzNums ) : sal_False);
2368cdf0e10cSrcweir if ( !bMatch )
2369cdf0e10cSrcweir nMatchedAllStrings = 0;
2370cdf0e10cSrcweir }
2371cdf0e10cSrcweir if ( nMatchedAllStrings )
2372cdf0e10cSrcweir eScannedType = eSetType;
2373cdf0e10cSrcweir else if ( bDidMatch )
2374cdf0e10cSrcweir return sal_False;
2375cdf0e10cSrcweir else
2376cdf0e10cSrcweir eScannedType = NUMBERFORMAT_NUMBER;
2377cdf0e10cSrcweir // everything else should have been recognized by now
2378cdf0e10cSrcweir }
2379cdf0e10cSrcweir else if ( eScannedType == NUMBERFORMAT_DATE )
2380cdf0e10cSrcweir { // the very relaxed date input checks may interfere with a preset format
2381cdf0e10cSrcweir nMatchedAllStrings &= ~nMatchedVirgin;
2382cdf0e10cSrcweir sal_Bool bWasReturn = ((nMatchedAllStrings & nMatchedUsedAsReturn) != 0);
2383cdf0e10cSrcweir if ( nMatchedAllStrings )
2384cdf0e10cSrcweir {
2385cdf0e10cSrcweir sal_Bool bMatch = (pFormat ? pFormat->IsNumForStringElementCountEqual(
2386cdf0e10cSrcweir nStringScanNumFor, nAnzStrings, nAnzNums ) : sal_False);
2387cdf0e10cSrcweir if ( !bMatch )
2388cdf0e10cSrcweir nMatchedAllStrings = 0;
2389cdf0e10cSrcweir }
2390cdf0e10cSrcweir if ( nMatchedAllStrings )
2391cdf0e10cSrcweir eScannedType = eSetType;
2392cdf0e10cSrcweir else if ( bWasReturn )
2393cdf0e10cSrcweir return sal_False;
2394cdf0e10cSrcweir }
2395cdf0e10cSrcweir else
2396cdf0e10cSrcweir nMatchedAllStrings = 0; // reset flag to no substrings matched
2397cdf0e10cSrcweir
2398cdf0e10cSrcweir return sal_True;
2399cdf0e10cSrcweir }
2400cdf0e10cSrcweir
2401cdf0e10cSrcweir
2402cdf0e10cSrcweir //---------------------------------------------------------------------------
2403cdf0e10cSrcweir // return sal_True or sal_False depending on the nMatched... state and remember usage
MatchedReturn()2404cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::MatchedReturn()
2405cdf0e10cSrcweir {
2406cdf0e10cSrcweir if ( nMatchedAllStrings & ~nMatchedVirgin )
2407cdf0e10cSrcweir {
2408cdf0e10cSrcweir nMatchedAllStrings |= nMatchedUsedAsReturn;
2409cdf0e10cSrcweir return sal_True;
2410cdf0e10cSrcweir }
2411cdf0e10cSrcweir return sal_False;
2412cdf0e10cSrcweir }
2413cdf0e10cSrcweir
2414cdf0e10cSrcweir
2415cdf0e10cSrcweir //---------------------------------------------------------------------------
2416cdf0e10cSrcweir // Initialize uppercase months and weekdays
2417cdf0e10cSrcweir
InitText()2418cdf0e10cSrcweir void ImpSvNumberInputScan::InitText()
2419cdf0e10cSrcweir {
2420cdf0e10cSrcweir sal_Int32 j, nElems;
2421cdf0e10cSrcweir const CharClass* pChrCls = pFormatter->GetCharClass();
2422cdf0e10cSrcweir const CalendarWrapper* pCal = pFormatter->GetCalendar();
2423cdf0e10cSrcweir delete [] pUpperMonthText;
2424cdf0e10cSrcweir delete [] pUpperAbbrevMonthText;
2425cdf0e10cSrcweir ::com::sun::star::uno::Sequence< ::com::sun::star::i18n::CalendarItem > xElems
2426cdf0e10cSrcweir = pCal->getMonths();
2427cdf0e10cSrcweir nElems = xElems.getLength();
2428cdf0e10cSrcweir pUpperMonthText = new String[nElems];
2429cdf0e10cSrcweir pUpperAbbrevMonthText = new String[nElems];
2430cdf0e10cSrcweir for ( j=0; j<nElems; j++ )
2431cdf0e10cSrcweir {
2432cdf0e10cSrcweir pUpperMonthText[j] = pChrCls->upper( xElems[j].FullName );
2433cdf0e10cSrcweir pUpperAbbrevMonthText[j] = pChrCls->upper( xElems[j].AbbrevName );
2434cdf0e10cSrcweir }
2435cdf0e10cSrcweir delete [] pUpperDayText;
2436cdf0e10cSrcweir delete [] pUpperAbbrevDayText;
2437cdf0e10cSrcweir xElems = pCal->getDays();
2438cdf0e10cSrcweir nElems = xElems.getLength();
2439cdf0e10cSrcweir pUpperDayText = new String[nElems];
2440cdf0e10cSrcweir pUpperAbbrevDayText = new String[nElems];
2441cdf0e10cSrcweir for ( j=0; j<nElems; j++ )
2442cdf0e10cSrcweir {
2443cdf0e10cSrcweir pUpperDayText[j] = pChrCls->upper( xElems[j].FullName );
2444cdf0e10cSrcweir pUpperAbbrevDayText[j] = pChrCls->upper( xElems[j].AbbrevName );
2445cdf0e10cSrcweir }
2446cdf0e10cSrcweir bTextInitialized = sal_True;
2447cdf0e10cSrcweir }
2448cdf0e10cSrcweir
2449cdf0e10cSrcweir
2450cdf0e10cSrcweir //===========================================================================
2451cdf0e10cSrcweir // P U B L I C
2452cdf0e10cSrcweir
2453cdf0e10cSrcweir //---------------------------------------------------------------------------
2454cdf0e10cSrcweir // ChangeIntl
2455cdf0e10cSrcweir //
2456cdf0e10cSrcweir // MUST be called if International/Locale is changed
2457cdf0e10cSrcweir
ChangeIntl()2458cdf0e10cSrcweir void ImpSvNumberInputScan::ChangeIntl()
2459cdf0e10cSrcweir {
2460cdf0e10cSrcweir sal_Unicode cDecSep = pFormatter->GetNumDecimalSep().GetChar(0);
2461cdf0e10cSrcweir bDecSepInDateSeps = ( cDecSep == '-' ||
2462cdf0e10cSrcweir cDecSep == '/' ||
2463cdf0e10cSrcweir cDecSep == '.' ||
2464cdf0e10cSrcweir cDecSep == pFormatter->GetDateSep().GetChar(0) );
2465cdf0e10cSrcweir bTextInitialized = sal_False;
2466cdf0e10cSrcweir aUpperCurrSymbol.Erase();
2467cdf0e10cSrcweir }
2468cdf0e10cSrcweir
2469cdf0e10cSrcweir
2470cdf0e10cSrcweir //---------------------------------------------------------------------------
2471cdf0e10cSrcweir // ChangeNullDate
2472cdf0e10cSrcweir
ChangeNullDate(const sal_uInt16 Day,const sal_uInt16 Month,const sal_uInt16 Year)2473cdf0e10cSrcweir void ImpSvNumberInputScan::ChangeNullDate(
2474cdf0e10cSrcweir const sal_uInt16 Day,
2475cdf0e10cSrcweir const sal_uInt16 Month,
2476cdf0e10cSrcweir const sal_uInt16 Year )
2477cdf0e10cSrcweir {
2478cdf0e10cSrcweir if ( pNullDate )
2479cdf0e10cSrcweir *pNullDate = Date(Day, Month, Year);
2480cdf0e10cSrcweir else
2481cdf0e10cSrcweir pNullDate = new Date(Day, Month, Year);
2482cdf0e10cSrcweir }
2483cdf0e10cSrcweir
2484cdf0e10cSrcweir
2485cdf0e10cSrcweir //---------------------------------------------------------------------------
2486cdf0e10cSrcweir // IsNumberFormat
2487cdf0e10cSrcweir //
2488cdf0e10cSrcweir // => does rString represent a number (also date, time et al)
2489cdf0e10cSrcweir
IsNumberFormat(const String & rString,short & F_Type,double & fOutNumber,const SvNumberformat * pFormat)2490cdf0e10cSrcweir sal_Bool ImpSvNumberInputScan::IsNumberFormat(
2491cdf0e10cSrcweir const String& rString, // string to be analyzed
2492cdf0e10cSrcweir short& F_Type, // IN: old type, OUT: new type
2493cdf0e10cSrcweir double& fOutNumber, // OUT: number if convertable
2494cdf0e10cSrcweir const SvNumberformat* pFormat ) // maybe a number format to match against
2495cdf0e10cSrcweir {
2496cdf0e10cSrcweir String sResString;
2497cdf0e10cSrcweir String aString;
2498cdf0e10cSrcweir sal_Bool res; // return value
2499cdf0e10cSrcweir eSetType = F_Type; // old type set
2500cdf0e10cSrcweir
2501cdf0e10cSrcweir if ( !rString.Len() )
2502cdf0e10cSrcweir res = sal_False;
2503cdf0e10cSrcweir else if (rString.Len() > 308) // arbitrary
2504cdf0e10cSrcweir res = sal_False;
2505cdf0e10cSrcweir else
2506cdf0e10cSrcweir {
2507cdf0e10cSrcweir // NoMoreUpperNeeded, all comparisons on UpperCase
2508cdf0e10cSrcweir aString = pFormatter->GetCharClass()->upper( rString );
2509cdf0e10cSrcweir // convert native number to ASCII if necessary
2510cdf0e10cSrcweir TransformInput( aString );
2511cdf0e10cSrcweir res = IsNumberFormatMain( aString, fOutNumber, pFormat );
2512cdf0e10cSrcweir }
2513cdf0e10cSrcweir
2514cdf0e10cSrcweir if (res)
2515cdf0e10cSrcweir {
2516cdf0e10cSrcweir if ( nNegCheck // ')' not found for '('
2517cdf0e10cSrcweir || (nSign && (eScannedType == NUMBERFORMAT_DATE
2518cdf0e10cSrcweir || eScannedType == NUMBERFORMAT_DATETIME))
2519cdf0e10cSrcweir ) // signed date/datetime
2520cdf0e10cSrcweir res = sal_False;
2521cdf0e10cSrcweir else
2522cdf0e10cSrcweir { // check count of partial number strings
2523cdf0e10cSrcweir switch (eScannedType)
2524cdf0e10cSrcweir {
2525cdf0e10cSrcweir case NUMBERFORMAT_PERCENT:
2526cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY:
2527cdf0e10cSrcweir case NUMBERFORMAT_NUMBER:
2528cdf0e10cSrcweir if (nDecPos == 1) // .05
2529cdf0e10cSrcweir {
2530cdf0e10cSrcweir // matched MidStrings function like group separators
2531cdf0e10cSrcweir if ( nMatchedAllStrings )
2532cdf0e10cSrcweir nThousand = nAnzNums - 1;
2533cdf0e10cSrcweir else if ( nAnzNums != 1 )
2534cdf0e10cSrcweir res = sal_False;
2535cdf0e10cSrcweir }
2536cdf0e10cSrcweir else if (nDecPos == 2) // 1.05
2537cdf0e10cSrcweir {
2538cdf0e10cSrcweir // matched MidStrings function like group separators
2539cdf0e10cSrcweir if ( nMatchedAllStrings )
2540cdf0e10cSrcweir nThousand = nAnzNums - 1;
2541cdf0e10cSrcweir else if ( nAnzNums != nThousand+2 )
2542cdf0e10cSrcweir res = sal_False;
2543cdf0e10cSrcweir }
2544cdf0e10cSrcweir else // 1,100 or 1,100.
2545cdf0e10cSrcweir {
2546cdf0e10cSrcweir // matched MidStrings function like group separators
2547cdf0e10cSrcweir if ( nMatchedAllStrings )
2548cdf0e10cSrcweir nThousand = nAnzNums - 1;
2549cdf0e10cSrcweir else if ( nAnzNums != nThousand+1 )
2550cdf0e10cSrcweir res = sal_False;
2551cdf0e10cSrcweir }
2552cdf0e10cSrcweir break;
2553cdf0e10cSrcweir
2554cdf0e10cSrcweir case NUMBERFORMAT_SCIENTIFIC: // 1.0e-2
2555cdf0e10cSrcweir if (nDecPos == 1) // .05
2556cdf0e10cSrcweir {
2557cdf0e10cSrcweir if (nAnzNums != 2)
2558cdf0e10cSrcweir res = sal_False;
2559cdf0e10cSrcweir }
2560cdf0e10cSrcweir else if (nDecPos == 2) // 1.05
2561cdf0e10cSrcweir {
2562cdf0e10cSrcweir if (nAnzNums != nThousand+3)
2563cdf0e10cSrcweir res = sal_False;
2564cdf0e10cSrcweir }
2565cdf0e10cSrcweir else // 1,100 or 1,100.
2566cdf0e10cSrcweir {
2567cdf0e10cSrcweir if (nAnzNums != nThousand+2)
2568cdf0e10cSrcweir res = sal_False;
2569cdf0e10cSrcweir }
2570cdf0e10cSrcweir break;
2571cdf0e10cSrcweir
2572cdf0e10cSrcweir case NUMBERFORMAT_DATE:
2573cdf0e10cSrcweir if (nMonth)
2574cdf0e10cSrcweir { // month name and numbers
2575cdf0e10cSrcweir if (nAnzNums > 2)
2576cdf0e10cSrcweir res = sal_False;
2577cdf0e10cSrcweir }
2578cdf0e10cSrcweir else
2579cdf0e10cSrcweir {
2580cdf0e10cSrcweir if (nAnzNums > 3)
2581cdf0e10cSrcweir res = sal_False;
2582cdf0e10cSrcweir }
2583cdf0e10cSrcweir break;
2584cdf0e10cSrcweir
2585cdf0e10cSrcweir case NUMBERFORMAT_TIME:
2586cdf0e10cSrcweir if (nDecPos)
2587cdf0e10cSrcweir { // hundredth seconds included
2588cdf0e10cSrcweir if (nAnzNums > 4)
2589cdf0e10cSrcweir res = sal_False;
2590cdf0e10cSrcweir }
2591cdf0e10cSrcweir else
2592cdf0e10cSrcweir {
2593cdf0e10cSrcweir if (nAnzNums > 3)
2594cdf0e10cSrcweir res = sal_False;
2595cdf0e10cSrcweir }
2596cdf0e10cSrcweir break;
2597cdf0e10cSrcweir
2598cdf0e10cSrcweir case NUMBERFORMAT_DATETIME:
2599cdf0e10cSrcweir if (nMonth)
2600cdf0e10cSrcweir { // month name and numbers
2601cdf0e10cSrcweir if (nDecPos)
2602cdf0e10cSrcweir { // hundredth seconds included
2603cdf0e10cSrcweir if (nAnzNums > 6)
2604cdf0e10cSrcweir res = sal_False;
2605cdf0e10cSrcweir }
2606cdf0e10cSrcweir else
2607cdf0e10cSrcweir {
2608cdf0e10cSrcweir if (nAnzNums > 5)
2609cdf0e10cSrcweir res = sal_False;
2610cdf0e10cSrcweir }
2611cdf0e10cSrcweir }
2612cdf0e10cSrcweir else
2613cdf0e10cSrcweir {
2614cdf0e10cSrcweir if (nDecPos)
2615cdf0e10cSrcweir { // hundredth seconds included
2616cdf0e10cSrcweir if (nAnzNums > 7)
2617cdf0e10cSrcweir res = sal_False;
2618cdf0e10cSrcweir }
2619cdf0e10cSrcweir else
2620cdf0e10cSrcweir {
2621cdf0e10cSrcweir if (nAnzNums > 6)
2622cdf0e10cSrcweir res = sal_False;
2623cdf0e10cSrcweir }
2624cdf0e10cSrcweir }
2625cdf0e10cSrcweir break;
2626cdf0e10cSrcweir
2627cdf0e10cSrcweir default:
2628cdf0e10cSrcweir break;
2629cdf0e10cSrcweir } // switch
2630cdf0e10cSrcweir } // else
2631cdf0e10cSrcweir } // if (res)
2632cdf0e10cSrcweir
2633cdf0e10cSrcweir if (res)
2634cdf0e10cSrcweir { // we finally have a number
2635cdf0e10cSrcweir switch (eScannedType)
2636cdf0e10cSrcweir {
2637cdf0e10cSrcweir case NUMBERFORMAT_LOGICAL:
2638cdf0e10cSrcweir if (nLogical == 1)
2639cdf0e10cSrcweir fOutNumber = 1.0; // True
2640cdf0e10cSrcweir else if (nLogical == -1)
2641cdf0e10cSrcweir fOutNumber = 0.0; // False
2642cdf0e10cSrcweir else
2643cdf0e10cSrcweir res = sal_False; // Oops
2644cdf0e10cSrcweir break;
2645cdf0e10cSrcweir
2646cdf0e10cSrcweir case NUMBERFORMAT_PERCENT:
2647cdf0e10cSrcweir case NUMBERFORMAT_CURRENCY:
2648cdf0e10cSrcweir case NUMBERFORMAT_NUMBER:
2649cdf0e10cSrcweir case NUMBERFORMAT_SCIENTIFIC:
2650cdf0e10cSrcweir case NUMBERFORMAT_DEFINED: // if no category detected handle as number
2651cdf0e10cSrcweir {
2652cdf0e10cSrcweir if ( nDecPos == 1 ) // . at start
2653cdf0e10cSrcweir sResString.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "0." ) );
2654cdf0e10cSrcweir else
2655cdf0e10cSrcweir sResString.Erase();
2656cdf0e10cSrcweir sal_uInt16 k;
2657cdf0e10cSrcweir for ( k = 0; k <= nThousand; k++)
2658cdf0e10cSrcweir sResString += sStrArray[nNums[k]]; // integer part
2659cdf0e10cSrcweir if ( nDecPos == 2 && k < nAnzNums ) // . somewhere
2660cdf0e10cSrcweir {
2661cdf0e10cSrcweir sResString += '.';
2662cdf0e10cSrcweir sal_uInt16 nStop = (eScannedType == NUMBERFORMAT_SCIENTIFIC ?
2663cdf0e10cSrcweir nAnzNums-1 : nAnzNums);
2664cdf0e10cSrcweir for ( ; k < nStop; k++)
2665cdf0e10cSrcweir sResString += sStrArray[nNums[k]]; // fractional part
2666cdf0e10cSrcweir }
2667cdf0e10cSrcweir
2668cdf0e10cSrcweir if (eScannedType != NUMBERFORMAT_SCIENTIFIC)
2669cdf0e10cSrcweir fOutNumber = StringToDouble(sResString);
2670cdf0e10cSrcweir else
2671cdf0e10cSrcweir { // append exponent
2672cdf0e10cSrcweir sResString += 'E';
2673cdf0e10cSrcweir if ( nESign == -1 )
2674cdf0e10cSrcweir sResString += '-';
2675cdf0e10cSrcweir sResString += sStrArray[nNums[nAnzNums-1]];
2676cdf0e10cSrcweir rtl_math_ConversionStatus eStatus;
2677cdf0e10cSrcweir fOutNumber = ::rtl::math::stringToDouble(
2678cdf0e10cSrcweir sResString, '.', ',', &eStatus, NULL );
2679cdf0e10cSrcweir if ( eStatus == rtl_math_ConversionStatus_OutOfRange )
2680cdf0e10cSrcweir {
2681cdf0e10cSrcweir F_Type = NUMBERFORMAT_TEXT; // overflow/underflow -> Text
2682cdf0e10cSrcweir if (nESign == -1)
2683cdf0e10cSrcweir fOutNumber = 0.0;
2684cdf0e10cSrcweir else
2685cdf0e10cSrcweir fOutNumber = DBL_MAX;
2686cdf0e10cSrcweir /*!*/ return sal_True;
2687cdf0e10cSrcweir }
2688cdf0e10cSrcweir }
2689cdf0e10cSrcweir
2690cdf0e10cSrcweir if ( nStringScanSign )
2691cdf0e10cSrcweir {
2692cdf0e10cSrcweir if ( nSign )
2693cdf0e10cSrcweir nSign *= nStringScanSign;
2694cdf0e10cSrcweir else
2695cdf0e10cSrcweir nSign = nStringScanSign;
2696cdf0e10cSrcweir }
2697cdf0e10cSrcweir if ( nSign < 0 )
2698cdf0e10cSrcweir fOutNumber = -fOutNumber;
2699cdf0e10cSrcweir
2700cdf0e10cSrcweir if (eScannedType == NUMBERFORMAT_PERCENT)
2701cdf0e10cSrcweir fOutNumber/= 100.0;
2702cdf0e10cSrcweir }
2703cdf0e10cSrcweir break;
2704cdf0e10cSrcweir
2705cdf0e10cSrcweir case NUMBERFORMAT_FRACTION:
2706cdf0e10cSrcweir if (nAnzNums == 1)
2707cdf0e10cSrcweir fOutNumber = StringToDouble(sStrArray[nNums[0]]);
2708cdf0e10cSrcweir else if (nAnzNums == 2)
2709cdf0e10cSrcweir {
2710cdf0e10cSrcweir if (nThousand == 1)
2711cdf0e10cSrcweir {
2712cdf0e10cSrcweir sResString = sStrArray[nNums[0]];
2713cdf0e10cSrcweir sResString += sStrArray[nNums[1]]; // integer part
2714cdf0e10cSrcweir fOutNumber = StringToDouble(sResString);
2715cdf0e10cSrcweir }
2716cdf0e10cSrcweir else
2717cdf0e10cSrcweir {
2718cdf0e10cSrcweir double fZaehler = StringToDouble(sStrArray[nNums[0]]);
2719cdf0e10cSrcweir double fNenner = StringToDouble(sStrArray[nNums[1]]);
2720cdf0e10cSrcweir if (fNenner != 0.0)
2721cdf0e10cSrcweir fOutNumber = fZaehler/fNenner;
2722cdf0e10cSrcweir else
2723cdf0e10cSrcweir res = sal_False;
2724cdf0e10cSrcweir }
2725cdf0e10cSrcweir }
2726cdf0e10cSrcweir else // nAnzNums > 2
2727cdf0e10cSrcweir {
2728cdf0e10cSrcweir sal_uInt16 k = 1;
2729cdf0e10cSrcweir sResString = sStrArray[nNums[0]];
2730cdf0e10cSrcweir if (nThousand > 0)
2731cdf0e10cSrcweir for (k = 1; k <= nThousand; k++)
2732cdf0e10cSrcweir sResString += sStrArray[nNums[k]];
2733cdf0e10cSrcweir fOutNumber = StringToDouble(sResString);
2734cdf0e10cSrcweir
2735cdf0e10cSrcweir if (k == nAnzNums-2)
2736cdf0e10cSrcweir {
2737cdf0e10cSrcweir double fZaehler = StringToDouble(sStrArray[nNums[k]]);
2738cdf0e10cSrcweir double fNenner = StringToDouble(sStrArray[nNums[k+1]]);
2739cdf0e10cSrcweir if (fNenner != 0.0)
2740cdf0e10cSrcweir fOutNumber += fZaehler/fNenner;
2741cdf0e10cSrcweir else
2742cdf0e10cSrcweir res = sal_False;
2743cdf0e10cSrcweir }
2744cdf0e10cSrcweir }
2745cdf0e10cSrcweir
2746cdf0e10cSrcweir if ( nStringScanSign )
2747cdf0e10cSrcweir {
2748cdf0e10cSrcweir if ( nSign )
2749cdf0e10cSrcweir nSign *= nStringScanSign;
2750cdf0e10cSrcweir else
2751cdf0e10cSrcweir nSign = nStringScanSign;
2752cdf0e10cSrcweir }
2753cdf0e10cSrcweir if ( nSign < 0 )
2754cdf0e10cSrcweir fOutNumber = -fOutNumber;
2755cdf0e10cSrcweir break;
2756cdf0e10cSrcweir
2757cdf0e10cSrcweir case NUMBERFORMAT_TIME:
2758cdf0e10cSrcweir GetTimeRef(fOutNumber, 0, nAnzNums);
2759cdf0e10cSrcweir if ( nSign < 0 )
2760cdf0e10cSrcweir fOutNumber = -fOutNumber;
2761cdf0e10cSrcweir break;
2762cdf0e10cSrcweir
2763cdf0e10cSrcweir case NUMBERFORMAT_DATE:
2764cdf0e10cSrcweir {
2765cdf0e10cSrcweir sal_uInt16 nCounter = 0; // dummy here
2766cdf0e10cSrcweir res = GetDateRef( fOutNumber, nCounter, pFormat );
2767cdf0e10cSrcweir }
2768cdf0e10cSrcweir break;
2769cdf0e10cSrcweir
2770cdf0e10cSrcweir case NUMBERFORMAT_DATETIME:
2771cdf0e10cSrcweir {
2772cdf0e10cSrcweir sal_uInt16 nCounter = 0; // needed here
2773cdf0e10cSrcweir res = GetDateRef( fOutNumber, nCounter, pFormat );
2774cdf0e10cSrcweir if ( res )
2775cdf0e10cSrcweir {
2776cdf0e10cSrcweir double fTime;
2777cdf0e10cSrcweir GetTimeRef( fTime, nCounter, nAnzNums - nCounter );
2778cdf0e10cSrcweir fOutNumber += fTime;
2779cdf0e10cSrcweir }
2780cdf0e10cSrcweir }
2781cdf0e10cSrcweir break;
2782cdf0e10cSrcweir
2783cdf0e10cSrcweir default:
2784cdf0e10cSrcweir DBG_ERRORFILE( "Some number recognized but what's it?" );
2785cdf0e10cSrcweir fOutNumber = 0.0;
2786cdf0e10cSrcweir break;
2787cdf0e10cSrcweir }
2788cdf0e10cSrcweir }
2789cdf0e10cSrcweir
2790cdf0e10cSrcweir if (res) // overflow/underflow -> Text
2791cdf0e10cSrcweir {
2792cdf0e10cSrcweir if (fOutNumber < -DBL_MAX) // -1.7E308
2793cdf0e10cSrcweir {
2794cdf0e10cSrcweir F_Type = NUMBERFORMAT_TEXT;
2795cdf0e10cSrcweir fOutNumber = -DBL_MAX;
2796cdf0e10cSrcweir return sal_True;
2797cdf0e10cSrcweir }
2798cdf0e10cSrcweir else if (fOutNumber > DBL_MAX) // 1.7E308
2799cdf0e10cSrcweir {
2800cdf0e10cSrcweir F_Type = NUMBERFORMAT_TEXT;
2801cdf0e10cSrcweir fOutNumber = DBL_MAX;
2802cdf0e10cSrcweir return sal_True;
2803cdf0e10cSrcweir }
2804cdf0e10cSrcweir }
2805cdf0e10cSrcweir
2806cdf0e10cSrcweir if (res == sal_False)
2807cdf0e10cSrcweir {
2808cdf0e10cSrcweir eScannedType = NUMBERFORMAT_TEXT;
2809cdf0e10cSrcweir fOutNumber = 0.0;
2810cdf0e10cSrcweir }
2811cdf0e10cSrcweir
2812cdf0e10cSrcweir F_Type = eScannedType;
2813cdf0e10cSrcweir return res;
2814cdf0e10cSrcweir }
2815cdf0e10cSrcweir
2816cdf0e10cSrcweir
2817cdf0e10cSrcweir
2818