xref: /aoo41x/main/svl/source/numbers/zforfind.cxx (revision dab0a4ea)
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