diff options
author | Kohei Yoshida <kyoshida@novell.com> | 2010-01-29 22:03:10 +0100 |
---|---|---|
committer | Kohei Yoshida <kyoshida@novell.com> | 2010-01-29 22:03:10 +0100 |
commit | 324721c3ef3715b002328683f8045c5bcfca0013 (patch) | |
tree | ad304244c9b1d3abdb5eb4e414fa6b4c26100125 /svl/source/numbers/zforscan.cxx | |
parent | 0ce0dd5863208500d8d4658f1f68f34e254ab015 (diff) | |
parent | 7f5f6c30e89c27422a1576ccceb9b0d79c8e3f0d (diff) |
rebased to m70
Diffstat (limited to 'svl/source/numbers/zforscan.cxx')
-rw-r--r-- | svl/source/numbers/zforscan.cxx | 2812 |
1 files changed, 2812 insertions, 0 deletions
diff --git a/svl/source/numbers/zforscan.cxx b/svl/source/numbers/zforscan.cxx new file mode 100644 index 000000000000..116ea4ce2f82 --- /dev/null +++ b/svl/source/numbers/zforscan.cxx @@ -0,0 +1,2812 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: zforscan.cxx,v $ + * $Revision: 1.49.140.2 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_svl.hxx" +#ifndef GCC +#endif + +#include <stdlib.h> +#include <tools/debug.hxx> +#include <i18npool/mslangid.hxx> +#include <unotools/charclass.hxx> +#include <unotools/localedatawrapper.hxx> +#include <unotools/numberformatcodewrapper.hxx> +#include <rtl/instance.hxx> + +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <unotools/digitgroupingiterator.hxx> + +#define _ZFORSCAN_CXX +#include "zforscan.hxx" +#undef _ZFORSCAN_CXX +#include "nfsymbol.hxx" +using namespace svt; + +const sal_Unicode cNonBreakingSpace = 0xA0; + +namespace +{ + struct ImplEnglishColors + { + const String* operator()() + { + static const String aEnglishColors[NF_MAX_DEFAULT_COLORS] = + { + String( RTL_CONSTASCII_USTRINGPARAM( "BLACK" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "BLUE" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "GREEN" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "CYAN" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "RED" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "MAGENTA" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "BROWN" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "GREY" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "YELLOW" ) ), + String( RTL_CONSTASCII_USTRINGPARAM( "WHITE" ) ) + }; + return &aEnglishColors[0]; + } + }; + + struct theEnglishColors + : public rtl::StaticAggregate< const String, ImplEnglishColors> {}; + +} + +ImpSvNumberformatScan::ImpSvNumberformatScan( SvNumberFormatter* pFormatterP ) +{ + pFormatter = pFormatterP; + bConvertMode = FALSE; + //! All keywords MUST be UPPERCASE! + sKeyword[NF_KEY_E].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) ); // Exponent + sKeyword[NF_KEY_AMPM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AM/PM" ) ); // AM/PM + sKeyword[NF_KEY_AP].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "A/P" ) ); // AM/PM short + sKeyword[NF_KEY_MI].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // Minute + sKeyword[NF_KEY_MMI].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // Minute 02 + sKeyword[NF_KEY_S].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "S" ) ); // Second + sKeyword[NF_KEY_SS].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SS" ) ); // Second 02 + sKeyword[NF_KEY_Q].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "Q" ) ); // Quarter short 'Q' + sKeyword[NF_KEY_QQ].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "QQ" ) ); // Quarter long + sKeyword[NF_KEY_NN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NN" ) ); // Day of week short + sKeyword[NF_KEY_NNN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNN" ) ); // Day of week long + sKeyword[NF_KEY_NNNN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "NNNN" ) ); // Day of week long incl. separator + sKeyword[NF_KEY_WW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WW" ) ); // Week of year + sKeyword[NF_KEY_CCC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CCC" ) ); // Currency abbreviation + bKeywordsNeedInit = TRUE; // locale dependent keywords + bCompatCurNeedInit = TRUE; // locale dependent compatibility currency strings + + StandardColor[0] = Color(COL_BLACK); + StandardColor[1] = Color(COL_LIGHTBLUE); + StandardColor[2] = Color(COL_LIGHTGREEN); + StandardColor[3] = Color(COL_LIGHTCYAN); + StandardColor[4] = Color(COL_LIGHTRED); + StandardColor[5] = Color(COL_LIGHTMAGENTA); + StandardColor[6] = Color(COL_BROWN); + StandardColor[7] = Color(COL_GRAY); + StandardColor[8] = Color(COL_YELLOW); + StandardColor[9] = Color(COL_WHITE); + + pNullDate = new Date(30,12,1899); + nStandardPrec = 2; + + sErrStr.AssignAscii( RTL_CONSTASCII_STRINGPARAM( "###" ) ); + Reset(); +} + +ImpSvNumberformatScan::~ImpSvNumberformatScan() +{ + delete pNullDate; + Reset(); +} + + +void ImpSvNumberformatScan::ChangeIntl() +{ + bKeywordsNeedInit = TRUE; + bCompatCurNeedInit = TRUE; + // may be initialized by InitSpecialKeyword() + sKeyword[NF_KEY_TRUE].Erase(); + sKeyword[NF_KEY_FALSE].Erase(); +} + + +void ImpSvNumberformatScan::InitSpecialKeyword( NfKeywordIndex eIdx ) const +{ + switch ( eIdx ) + { + case NF_KEY_TRUE : + ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE] = + pFormatter->GetCharClass()->upper( + pFormatter->GetLocaleData()->getTrueWord() ); + if ( !sKeyword[NF_KEY_TRUE].Len() ) + { + DBG_ERRORFILE( "InitSpecialKeyword: TRUE_WORD?" ); + ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_TRUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TRUE" ) ); + } + break; + case NF_KEY_FALSE : + ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE] = + pFormatter->GetCharClass()->upper( + pFormatter->GetLocaleData()->getFalseWord() ); + if ( !sKeyword[NF_KEY_FALSE].Len() ) + { + DBG_ERRORFILE( "InitSpecialKeyword: FALSE_WORD?" ); + ((ImpSvNumberformatScan*)this)->sKeyword[NF_KEY_FALSE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FALSE" ) ); + } + break; + default: + DBG_ERRORFILE( "InitSpecialKeyword: unknown request" ); + } +} + + +void ImpSvNumberformatScan::InitCompatCur() const +{ + ImpSvNumberformatScan* pThis = (ImpSvNumberformatScan*)this; + // currency symbol for old style ("automatic") compatibility format codes + pFormatter->GetCompatibilityCurrency( pThis->sCurSymbol, pThis->sCurAbbrev ); + // currency symbol upper case + pThis->sCurString = pFormatter->GetCharClass()->upper( sCurSymbol ); + bCompatCurNeedInit = FALSE; +} + + +void ImpSvNumberformatScan::InitKeywords() const +{ + if ( !bKeywordsNeedInit ) + return ; + ((ImpSvNumberformatScan*)this)->SetDependentKeywords(); + bKeywordsNeedInit = FALSE; +} + + +/** Extract the name of General, Standard, Whatever, ignoring leading modifiers + such as [NatNum1]. */ +static String lcl_extractStandardGeneralName( const ::rtl::OUString & rCode ) +{ + String aStr; + const sal_Unicode* p = rCode.getStr(); + const sal_Unicode* const pStop = p + rCode.getLength(); + const sal_Unicode* pBeg = p; // name begins here + bool bMod = false; + bool bDone = false; + while (p < pStop && !bDone) + { + switch (*p) + { + case '[': + bMod = true; + break; + case ']': + if (bMod) + { + bMod = false; + pBeg = p+1; + } + // else: would be a locale data error, easily to be spotted in + // UI dialog + break; + case ';': + if (!bMod) + { + bDone = true; + --p; // put back, increment by one follows + } + break; + } + ++p; + if (bMod) + pBeg = p; + } + if (pBeg < p) + aStr = rCode.copy( pBeg - rCode.getStr(), p - pBeg); + return aStr; +} + + +void ImpSvNumberformatScan::SetDependentKeywords() +{ + using namespace ::com::sun::star; + using namespace ::com::sun::star::uno; + + const CharClass* pCharClass = pFormatter->GetCharClass(); + const LocaleDataWrapper* pLocaleData = pFormatter->GetLocaleData(); + // #80023# be sure to generate keywords for the loaded Locale, not for the + // requested Locale, otherwise number format codes might not match + lang::Locale aLoadedLocale = pLocaleData->getLoadedLocale(); + LanguageType eLang = MsLangId::convertLocaleToLanguage( aLoadedLocale ); + NumberFormatCodeWrapper aNumberFormatCode( pFormatter->GetServiceManager(), aLoadedLocale ); + + i18n::NumberFormatCode aFormat = aNumberFormatCode.getFormatCode( NF_NUMBER_STANDARD ); + sNameStandardFormat = lcl_extractStandardGeneralName( aFormat.Code); + sKeyword[NF_KEY_GENERAL] = pCharClass->upper( sNameStandardFormat ); + + // preset new calendar keywords + sKeyword[NF_KEY_AAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAA" ) ); + sKeyword[NF_KEY_AAAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) ); + sKeyword[NF_KEY_EC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "E" ) ); + sKeyword[NF_KEY_EEC].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "EE" ) ); + sKeyword[NF_KEY_G].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) ); + sKeyword[NF_KEY_GG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) ); + sKeyword[NF_KEY_GGG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) ); + sKeyword[NF_KEY_R].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "R" ) ); + sKeyword[NF_KEY_RR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RR" ) ); + + // Thai T NatNum special. Other locale's small letter 't' results in upper + // case comparison not matching but length does in conversion mode. Ugly. + if (eLang == LANGUAGE_THAI) + sKeyword[NF_KEY_THAI_T].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T")); + else + sKeyword[NF_KEY_THAI_T].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "t")); + + switch ( eLang ) + { + case LANGUAGE_GERMAN: + case LANGUAGE_GERMAN_SWISS: + case LANGUAGE_GERMAN_AUSTRIAN: + case LANGUAGE_GERMAN_LUXEMBOURG: + case LANGUAGE_GERMAN_LIECHTENSTEIN: + { + //! all capital letters + sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); // month 1 + sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); // month 01 + sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) ); // month Jan + sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) ); // month Januar + sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) );// month J + sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) ); // hour 2 + sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) ); // hour 02 + sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) ); + sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) ); + sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTT" ) ); + sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TTTT" ) ); + sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) ); + sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) ); + sKeyword[NF_KEY_BOOLEAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "LOGISCH" ) ); + sKeyword[NF_KEY_COLOR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "FARBE" ) ); + sKeyword[NF_KEY_BLACK].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "SCHWARZ" ) ); + sKeyword[NF_KEY_BLUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLAU" ) ); + sKeyword[NF_KEY_GREEN] = UniString( "GR" "\xDC" "N", RTL_TEXTENCODING_ISO_8859_1 ); + sKeyword[NF_KEY_CYAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) ); + sKeyword[NF_KEY_RED].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "ROT" ) ); + sKeyword[NF_KEY_MAGENTA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) ); + sKeyword[NF_KEY_BROWN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BRAUN" ) ); + sKeyword[NF_KEY_GREY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GRAU" ) ); + sKeyword[NF_KEY_YELLOW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GELB" ) ); + sKeyword[NF_KEY_WHITE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WEISS" ) ); + } + break; + default: + { + // day + switch ( eLang ) + { + case LANGUAGE_ITALIAN : + case LANGUAGE_ITALIAN_SWISS : + sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "G" ) ); + sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GG" ) ); + sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGG" ) ); + sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GGGG" ) ); + // must exchange the era code, same as Xcl + sKeyword[NF_KEY_G].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "X" ) ); + sKeyword[NF_KEY_GG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XX" ) ); + sKeyword[NF_KEY_GGG].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "XXX" ) ); + break; + case LANGUAGE_FRENCH : + case LANGUAGE_FRENCH_BELGIAN : + case LANGUAGE_FRENCH_CANADIAN : + case LANGUAGE_FRENCH_SWISS : + case LANGUAGE_FRENCH_LUXEMBOURG : + case LANGUAGE_FRENCH_MONACO : + sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "J" ) ); + sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) ); + sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJ" ) ); + sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) ); + break; + case LANGUAGE_FINNISH : + sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "P" ) ); + sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PP" ) ); + sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPP" ) ); + sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "PPPP" ) ); + break; + default: + sKeyword[NF_KEY_D].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "D" ) ); + sKeyword[NF_KEY_DD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DD" ) ); + sKeyword[NF_KEY_DDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDD" ) ); + sKeyword[NF_KEY_DDDD].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "DDDD" ) ); + } + // month + switch ( eLang ) + { + case LANGUAGE_FINNISH : + sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "K" ) ); + sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KK" ) ); + sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKK" ) ); + sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKK" ) ); + sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "KKKKK" ) ); + break; + default: + sKeyword[NF_KEY_M].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "M" ) ); + sKeyword[NF_KEY_MM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MM" ) ); + sKeyword[NF_KEY_MMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMM" ) ); + sKeyword[NF_KEY_MMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMM" ) ); + sKeyword[NF_KEY_MMMMM].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MMMMM" ) ); + } + // year + switch ( eLang ) + { + case LANGUAGE_ITALIAN : + case LANGUAGE_ITALIAN_SWISS : + case LANGUAGE_FRENCH : + case LANGUAGE_FRENCH_BELGIAN : + case LANGUAGE_FRENCH_CANADIAN : + case LANGUAGE_FRENCH_SWISS : + case LANGUAGE_FRENCH_LUXEMBOURG : + case LANGUAGE_FRENCH_MONACO : + case LANGUAGE_PORTUGUESE : + case LANGUAGE_PORTUGUESE_BRAZILIAN : + case LANGUAGE_SPANISH_MODERN : + case LANGUAGE_SPANISH_DATED : + case LANGUAGE_SPANISH_MEXICAN : + case LANGUAGE_SPANISH_GUATEMALA : + case LANGUAGE_SPANISH_COSTARICA : + case LANGUAGE_SPANISH_PANAMA : + case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC : + case LANGUAGE_SPANISH_VENEZUELA : + case LANGUAGE_SPANISH_COLOMBIA : + case LANGUAGE_SPANISH_PERU : + case LANGUAGE_SPANISH_ARGENTINA : + case LANGUAGE_SPANISH_ECUADOR : + case LANGUAGE_SPANISH_CHILE : + case LANGUAGE_SPANISH_URUGUAY : + case LANGUAGE_SPANISH_PARAGUAY : + case LANGUAGE_SPANISH_BOLIVIA : + case LANGUAGE_SPANISH_EL_SALVADOR : + case LANGUAGE_SPANISH_HONDURAS : + case LANGUAGE_SPANISH_NICARAGUA : + case LANGUAGE_SPANISH_PUERTO_RICO : + sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AA" ) ); + sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "AAAA" ) ); + // must exchange the day of week name code, same as Xcl + sKeyword[NF_KEY_AAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOO" ) ); + sKeyword[NF_KEY_AAAA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "OOOO" ) ); + break; + case LANGUAGE_DUTCH : + case LANGUAGE_DUTCH_BELGIAN : + sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJ" ) ); + sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "JJJJ" ) ); + break; + case LANGUAGE_FINNISH : + sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VV" ) ); + sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "VVVV" ) ); + break; + default: + sKeyword[NF_KEY_YY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YY" ) ); + sKeyword[NF_KEY_YYYY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YYYY" ) ); + } + // hour + switch ( eLang ) + { + case LANGUAGE_DUTCH : + case LANGUAGE_DUTCH_BELGIAN : + sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "U" ) ); + sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "UU" ) ); + break; + case LANGUAGE_FINNISH : + case LANGUAGE_SWEDISH : + case LANGUAGE_SWEDISH_FINLAND : + case LANGUAGE_DANISH : + case LANGUAGE_NORWEGIAN : + case LANGUAGE_NORWEGIAN_BOKMAL : + case LANGUAGE_NORWEGIAN_NYNORSK : + sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "T" ) ); + sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "TT" ) ); + break; + default: + sKeyword[NF_KEY_H].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "H" ) ); + sKeyword[NF_KEY_HH].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "HH" ) ); + } + // boolean + sKeyword[NF_KEY_BOOLEAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BOOLEAN" ) ); + // colours + sKeyword[NF_KEY_COLOR].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "COLOR" ) ); + sKeyword[NF_KEY_BLACK].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLACK" ) ); + sKeyword[NF_KEY_BLUE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BLUE" ) ); + sKeyword[NF_KEY_GREEN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREEN" ) ); + sKeyword[NF_KEY_CYAN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "CYAN" ) ); + sKeyword[NF_KEY_RED].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "RED" ) ); + sKeyword[NF_KEY_MAGENTA].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "MAGENTA" ) ); + sKeyword[NF_KEY_BROWN].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "BROWN" ) ); + sKeyword[NF_KEY_GREY].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "GREY" ) ); + sKeyword[NF_KEY_YELLOW].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "YELLOW" ) ); + sKeyword[NF_KEY_WHITE].AssignAscii( RTL_CONSTASCII_STRINGPARAM( "WHITE" ) ); + } + break; + } + + // boolean keyords + InitSpecialKeyword( NF_KEY_TRUE ); + InitSpecialKeyword( NF_KEY_FALSE ); + + // compatibility currency strings + InitCompatCur(); +} + + +void ImpSvNumberformatScan::ChangeNullDate(USHORT nDay, USHORT nMonth, USHORT nYear) +{ + if ( pNullDate ) + *pNullDate = Date(nDay, nMonth, nYear); + else + pNullDate = new Date(nDay, nMonth, nYear); +} + +void ImpSvNumberformatScan::ChangeStandardPrec(sal_uInt16 nPrec) +{ + nStandardPrec = nPrec; +} + +Color* ImpSvNumberformatScan::GetColor(String& sStr) +{ + String sString = pFormatter->GetCharClass()->upper(sStr); + const String* pKeyword = GetKeywords(); + size_t i = 0; + while (i < NF_MAX_DEFAULT_COLORS && + sString != pKeyword[NF_KEY_FIRSTCOLOR+i] ) + i++; + if ( i >= NF_MAX_DEFAULT_COLORS ) + { + const String* pEnglishColors = theEnglishColors::get(); + size_t j = 0; + while ( j < NF_MAX_DEFAULT_COLORS && + sString != pEnglishColors[j] ) + ++j; + if ( j < NF_MAX_DEFAULT_COLORS ) + i = j; + } + + Color* pResult = NULL; + if (i >= NF_MAX_DEFAULT_COLORS) + { + const String& rColorWord = pKeyword[NF_KEY_COLOR]; + xub_StrLen nPos = sString.Match(rColorWord); + if (nPos > 0) + { + sStr.Erase(0, nPos); + sStr.EraseLeadingChars(); + sStr.EraseTrailingChars(); + if (bConvertMode) + { + pFormatter->ChangeIntl(eNewLnge); + sStr.Insert( GetKeywords()[NF_KEY_COLOR], 0 ); // Color -> FARBE + pFormatter->ChangeIntl(eTmpLnge); + } + else + sStr.Insert(rColorWord,0); + sString.Erase(0, nPos); + sString.EraseLeadingChars(); + sString.EraseTrailingChars(); + + if ( CharClass::isAsciiNumeric( sString ) ) + { + long nIndex = sString.ToInt32(); + if (nIndex > 0 && nIndex <= 64) + pResult = pFormatter->GetUserDefColor((USHORT)nIndex-1); + } + } + } + else + { + sStr.Erase(); + if (bConvertMode) + { + pFormatter->ChangeIntl(eNewLnge); + sStr = GetKeywords()[NF_KEY_FIRSTCOLOR+i]; // red -> rot + pFormatter->ChangeIntl(eTmpLnge); + } + else + sStr = pKeyword[NF_KEY_FIRSTCOLOR+i]; + + pResult = &(StandardColor[i]); + } + return pResult; +} + + +short ImpSvNumberformatScan::GetKeyWord( const String& sSymbol, xub_StrLen nPos ) +{ + String sString = pFormatter->GetCharClass()->toUpper( sSymbol, nPos, sSymbol.Len() - nPos ); + const String* pKeyword = GetKeywords(); + // #77026# for the Xcl perverts: the GENERAL keyword is recognized anywhere + if ( sString.Search( pKeyword[NF_KEY_GENERAL] ) == 0 ) + return NF_KEY_GENERAL; + //! MUST be a reverse search to find longer strings first + short i = NF_KEYWORD_ENTRIES_COUNT-1; + BOOL bFound = FALSE; + for ( ; i > NF_KEY_LASTKEYWORD_SO5; --i ) + { + bFound = sString.Search(pKeyword[i]) == 0; + if ( bFound ) + { + break; + } + } + // new keywords take precedence over old keywords + if ( !bFound ) + { // skip the gap of colors et al between new and old keywords and search on + i = NF_KEY_LASTKEYWORD; + while ( i > 0 && sString.Search(pKeyword[i]) != 0 ) + i--; + if ( i > NF_KEY_LASTOLDKEYWORD && sString != pKeyword[i] ) + { // found something, but maybe it's something else? + // e.g. new NNN is found in NNNN, for NNNN we must search on + short j = i - 1; + while ( j > 0 && sString.Search(pKeyword[j]) != 0 ) + j--; + if ( j && pKeyword[j].Len() > pKeyword[i].Len() ) + return j; + } + } + // The Thai T NatNum modifier during Xcl import. + if (i == 0 && bConvertMode && sString.GetChar(0) == 'T' && eTmpLnge == + LANGUAGE_ENGLISH_US && MsLangId::getRealLanguage( eNewLnge) == + LANGUAGE_THAI) + i = NF_KEY_THAI_T; + return i; // 0 => not found +} + +//--------------------------------------------------------------------------- +// Next_Symbol +//--------------------------------------------------------------------------- +// Zerlegt die Eingabe in Symbole fuer die weitere +// Verarbeitung (Turing-Maschine). +//--------------------------------------------------------------------------- +// Ausgangs Zustand = SsStart +//---------------+-------------------+-----------------------+--------------- +// Alter Zustand | gelesenes Zeichen | Aktion | Neuer Zustand +//---------------+-------------------+-----------------------+--------------- +// SsStart | Buchstabe | Symbol=Zeichen | SsGetWord +// | " | Typ = String | SsGetString +// | \ | Typ = String | SsGetChar +// | * | Typ = Star | SsGetStar +// | _ | Typ = Blank | SsGetBlank +// | @ # 0 ? / . , % [ | Symbol = Zeichen; | +// | ] ' Blank | Typ = Steuerzeichen | SsStop +// | $ - + ( ) : | Typ = String; | +// | | | Typ = Comment | SsStop +// | Sonst | Symbol = Zeichen | SsStop +//---------------|-------------------+-----------------------+--------------- +// SsGetChar | Sonst | Symbol=Zeichen | SsStop +//---------------+-------------------+-----------------------+--------------- +// GetString | " | | SsStop +// | Sonst | Symbol+=Zeichen | GetString +//---------------+-------------------+-----------------------+--------------- +// SsGetWord | Buchstabe | Symbol += Zeichen | +// | + - (E+ E-)| Symbol += Zeichen | SsStop +// | / (AM/PM)| Symbol += Zeichen | +// | Sonst | Pos--, if Key Typ=Word| SsStop +//---------------+-------------------+-----------------------+--------------- +// SsGetStar | Sonst | Symbol+=Zeichen | SsStop +// | | markiere Sonderfall * | +//---------------+-------------------+-----------------------+--------------- +// SsGetBlank | Sonst | Symbol+=Zeichen | SsStop +// | | markiere Sonderfall _ | +//---------------+-------------------+-----------------------+--------------- +// Wurde im State SsGetWord ein Schluesselwort erkannt (auch als +// Anfangsteilwort des Symbols) +// so werden die restlichen Buchstaben zurueckgeschrieben !! + +enum ScanState +{ + SsStop = 0, + SsStart = 1, + SsGetChar = 2, + SsGetString = 3, + SsGetWord = 4, + SsGetStar = 5, + SsGetBlank = 6 +}; + +short ImpSvNumberformatScan::Next_Symbol( const String& rStr, + xub_StrLen& nPos, String& sSymbol ) +{ + if ( bKeywordsNeedInit ) + InitKeywords(); + const CharClass* pChrCls = pFormatter->GetCharClass(); + const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData(); + const xub_StrLen nStart = nPos; + short eType = 0; + ScanState eState = SsStart; + sSymbol.Erase(); + while ( nPos < rStr.Len() && eState != SsStop ) + { + sal_Unicode cToken = rStr.GetChar( nPos++ ); + switch (eState) + { + case SsStart: + { + // Fetch any currency longer than one character and don't get + // confused later on by "E/" or other combinations of letters + // and meaningful symbols. Necessary for old automatic currency. + // #96158# But don't do it if we're starting a "[...]" section, + // for example a "[$...]" new currency symbol to not parse away + // "$U" (symbol) of "[$UYU]" (abbreviation). + if ( nCurrPos != STRING_NOTFOUND && sCurString.Len() > 1 && + nPos-1 + sCurString.Len() <= rStr.Len() && + !(nPos > 1 && rStr.GetChar( nPos-2 ) == '[') ) + { + String aTest( rStr.Copy( nPos-1, sCurString.Len() ) ); + pChrCls->toUpper( aTest ); + if ( aTest == sCurString ) + { + sSymbol = rStr.Copy( --nPos, sCurString.Len() ); + nPos = nPos + sSymbol.Len(); + eState = SsStop; + eType = NF_SYMBOLTYPE_STRING; + return eType; + } + } + switch (cToken) + { + case '#': + case '0': + case '?': + case '%': + case '@': + case '[': + case ']': + case ',': + case '.': + case '/': + case '\'': + case ' ': + case ':': + case '-': + { + eType = NF_SYMBOLTYPE_DEL; + sSymbol += cToken; + eState = SsStop; + } + break; + case '*': + { + eType = NF_SYMBOLTYPE_STAR; + sSymbol += cToken; + eState = SsGetStar; + } + break; + case '_': + { + eType = NF_SYMBOLTYPE_BLANK; + sSymbol += cToken; + eState = SsGetBlank; + } + break; +#if NF_COMMENT_IN_FORMATSTRING + case '{': + eType = NF_SYMBOLTYPE_COMMENT; + eState = SsStop; + sSymbol.Append( rStr.GetBuffer() + (nPos-1), rStr.Len() - (nPos-1) ); + nPos = rStr.Len(); + break; +#endif + case '"': + eType = NF_SYMBOLTYPE_STRING; + eState = SsGetString; + sSymbol += cToken; + break; + case '\\': + eType = NF_SYMBOLTYPE_STRING; + eState = SsGetChar; + sSymbol += cToken; + break; + case '$': + case '+': + case '(': + case ')': + eType = NF_SYMBOLTYPE_STRING; + eState = SsStop; + sSymbol += cToken; + break; + default : + { + if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cToken) || + StringEqualsChar( pFormatter->GetNumThousandSep(), cToken) || + StringEqualsChar( pFormatter->GetDateSep(), cToken) || + StringEqualsChar( pLoc->getTimeSep(), cToken) || + StringEqualsChar( pLoc->getTime100SecSep(), cToken)) + { + // Another separator than pre-known ASCII + eType = NF_SYMBOLTYPE_DEL; + sSymbol += cToken; + eState = SsStop; + } + else if ( pChrCls->isLetter( rStr, nPos-1 ) ) + { + short nTmpType = GetKeyWord( rStr, nPos-1 ); + if ( nTmpType ) + { + BOOL bCurrency = FALSE; + // "Automatic" currency may start with keyword, + // like "R" (Rand) and 'R' (era) + if ( nCurrPos != STRING_NOTFOUND && + nPos-1 + sCurString.Len() <= rStr.Len() && + sCurString.Search( sKeyword[nTmpType] ) == 0 ) + { + String aTest( rStr.Copy( nPos-1, sCurString.Len() ) ); + pChrCls->toUpper( aTest ); + if ( aTest == sCurString ) + bCurrency = TRUE; + } + if ( bCurrency ) + { + eState = SsGetWord; + sSymbol += cToken; + } + else + { + eType = nTmpType; + xub_StrLen nLen = sKeyword[eType].Len(); + sSymbol = rStr.Copy( nPos-1, nLen ); + if ( eType == NF_KEY_E || IsAmbiguousE( eType ) ) + { + sal_Unicode cNext = rStr.GetChar(nPos); + switch ( cNext ) + { + case '+' : + case '-' : // E+ E- combine to one symbol + sSymbol += cNext; + eType = NF_KEY_E; + nPos++; + break; + case '0' : + case '#' : // scientific E without sign + eType = NF_KEY_E; + break; + } + } + nPos--; + nPos = nPos + nLen; + eState = SsStop; + } + } + else + { + eState = SsGetWord; + sSymbol += cToken; + } + } + else + { + eType = NF_SYMBOLTYPE_STRING; + eState = SsStop; + sSymbol += cToken; + } + } + break; + } + } + break; + case SsGetChar: + { + sSymbol += cToken; + eState = SsStop; + } + break; + case SsGetString: + { + if (cToken == '"') + eState = SsStop; + sSymbol += cToken; + } + break; + case SsGetWord: + { + if ( pChrCls->isLetter( rStr, nPos-1 ) ) + { + short nTmpType = GetKeyWord( rStr, nPos-1 ); + if ( nTmpType ) + { // beginning of keyword, stop scan and put back + eType = NF_SYMBOLTYPE_STRING; + eState = SsStop; + nPos--; + } + else + sSymbol += cToken; + } + else + { + BOOL bDontStop = FALSE; + switch (cToken) + { + case '/': // AM/PM, A/P + { + sal_Unicode cNext = rStr.GetChar(nPos); + if ( cNext == 'P' || cNext == 'p' ) + { + xub_StrLen nLen = sSymbol.Len(); + if ( 1 <= nLen + && (sSymbol.GetChar(0) == 'A' || sSymbol.GetChar(0) == 'a') + && (nLen == 1 || (nLen == 2 + && (sSymbol.GetChar(1) == 'M' || sSymbol.GetChar(1) == 'm') + && (rStr.GetChar(nPos+1) == 'M' || rStr.GetChar(nPos+1) == 'm'))) ) + { + sSymbol += cToken; + bDontStop = TRUE; + } + } + } + break; + } + // anything not recognized will stop the scan + if ( eState != SsStop && !bDontStop ) + { + eState = SsStop; + nPos--; + eType = NF_SYMBOLTYPE_STRING; + } + } + } + break; + case SsGetStar: + { + eState = SsStop; + sSymbol += cToken; + nRepPos = (nPos - nStart) - 1; // everytime > 0!! + } + break; + case SsGetBlank: + { + eState = SsStop; + sSymbol += cToken; + } + break; + default: + break; + } // of switch + } // of while + if (eState == SsGetWord) + eType = NF_SYMBOLTYPE_STRING; + return eType; +} + +xub_StrLen ImpSvNumberformatScan::Symbol_Division(const String& rString) +{ + nCurrPos = STRING_NOTFOUND; + // Ist Waehrung im Spiel? + String sString = pFormatter->GetCharClass()->upper(rString); + xub_StrLen nCPos = 0; + while (nCPos != STRING_NOTFOUND) + { + nCPos = sString.Search(GetCurString(),nCPos); + if (nCPos != STRING_NOTFOUND) + { + // in Quotes? + xub_StrLen nQ = SvNumberformat::GetQuoteEnd( sString, nCPos ); + if ( nQ == STRING_NOTFOUND ) + { + sal_Unicode c; + if ( nCPos == 0 || + ((c = sString.GetChar(xub_StrLen(nCPos-1))) != '"' + && c != '\\') ) // dm kann durch "dm + { // \d geschuetzt werden + nCurrPos = nCPos; + nCPos = STRING_NOTFOUND; // Abbruch + } + else + nCPos++; // weitersuchen + } + else + nCPos = nQ + 1; // weitersuchen + } + } + nAnzStrings = 0; + BOOL bStar = FALSE; // wird bei '*'Detektion gesetzt + Reset(); + + xub_StrLen nPos = 0; + const xub_StrLen nLen = rString.Len(); + while (nPos < nLen && nAnzStrings < NF_MAX_FORMAT_SYMBOLS) + { + nTypeArray[nAnzStrings] = Next_Symbol(rString, nPos, sStrArray[nAnzStrings]); + if (nTypeArray[nAnzStrings] == NF_SYMBOLTYPE_STAR) + { // Ueberwachung des '*' + if (bStar) + return nPos; // Fehler: doppelter '*' + else + bStar = TRUE; + } + nAnzStrings++; + } + + return 0; // 0 => ok +} + +void ImpSvNumberformatScan::SkipStrings(USHORT& i, xub_StrLen& nPos) +{ + while (i < nAnzStrings && ( nTypeArray[i] == NF_SYMBOLTYPE_STRING + || nTypeArray[i] == NF_SYMBOLTYPE_BLANK + || nTypeArray[i] == NF_SYMBOLTYPE_STAR) ) + { + nPos = nPos + sStrArray[i].Len(); + i++; + } +} + + +USHORT ImpSvNumberformatScan::PreviousKeyword(USHORT i) +{ + short res = 0; + if (i > 0 && i < nAnzStrings) + { + i--; + while (i > 0 && nTypeArray[i] <= 0) + i--; + if (nTypeArray[i] > 0) + res = nTypeArray[i]; + } + return res; +} + +USHORT ImpSvNumberformatScan::NextKeyword(USHORT i) +{ + short res = 0; + if (i < nAnzStrings-1) + { + i++; + while (i < nAnzStrings-1 && nTypeArray[i] <= 0) + i++; + if (nTypeArray[i] > 0) + res = nTypeArray[i]; + } + return res; +} + +short ImpSvNumberformatScan::PreviousType( USHORT i ) +{ + if ( i > 0 && i < nAnzStrings ) + { + do + { + i--; + } while ( i > 0 && nTypeArray[i] == NF_SYMBOLTYPE_EMPTY ); + return nTypeArray[i]; + } + return 0; +} + +sal_Unicode ImpSvNumberformatScan::PreviousChar(USHORT i) +{ + sal_Unicode res = ' '; + if (i > 0 && i < nAnzStrings) + { + i--; + while (i > 0 && ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY + || nTypeArray[i] == NF_SYMBOLTYPE_STRING + || nTypeArray[i] == NF_SYMBOLTYPE_STAR + || nTypeArray[i] == NF_SYMBOLTYPE_BLANK ) ) + i--; + if (sStrArray[i].Len() > 0) + res = sStrArray[i].GetChar(xub_StrLen(sStrArray[i].Len()-1)); + } + return res; +} + +sal_Unicode ImpSvNumberformatScan::NextChar(USHORT i) +{ + sal_Unicode res = ' '; + if (i < nAnzStrings-1) + { + i++; + while (i < nAnzStrings-1 && + ( nTypeArray[i] == NF_SYMBOLTYPE_EMPTY + || nTypeArray[i] == NF_SYMBOLTYPE_STRING + || nTypeArray[i] == NF_SYMBOLTYPE_STAR + || nTypeArray[i] == NF_SYMBOLTYPE_BLANK)) + i++; + if (sStrArray[i].Len() > 0) + res = sStrArray[i].GetChar(0); + } + return res; +} + +BOOL ImpSvNumberformatScan::IsLastBlankBeforeFrac(USHORT i) +{ + BOOL res = TRUE; + if (i < nAnzStrings-1) + { + BOOL bStop = FALSE; + i++; + while (i < nAnzStrings-1 && !bStop) + { + i++; + if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL && + sStrArray[i].GetChar(0) == '/') + bStop = TRUE; + else if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL && + sStrArray[i].GetChar(0) == ' ') + res = FALSE; + } + if (!bStop) // kein '/' + res = FALSE; + } + else + res = FALSE; // kein '/' mehr + + return res; +} + +void ImpSvNumberformatScan::Reset() +{ + nAnzStrings = 0; + nAnzResStrings = 0; +#if 0 +// ER 20.06.97 14:05 nicht noetig, wenn nAnzStrings beachtet wird + for (size_t i = 0; i < NF_MAX_FORMAT_SYMBOLS; i++) + { + sStrArray[i].Erase(); + nTypeArray[i] = 0; + } +#endif + eScannedType = NUMBERFORMAT_UNDEFINED; + nRepPos = 0; + bExp = FALSE; + bThousand = FALSE; + nThousand = 0; + bDecSep = FALSE; + nDecPos = -1; + nExpPos = (USHORT) -1; + nBlankPos = (USHORT) -1; + nCntPre = 0; + nCntPost = 0; + nCntExp = 0; + bFrac = FALSE; + bBlank = FALSE; + nNatNumModifier = 0; +} + + +BOOL ImpSvNumberformatScan::Is100SecZero( USHORT i, BOOL bHadDecSep ) +{ + USHORT nIndexPre = PreviousKeyword( i ); + return (nIndexPre == NF_KEY_S || nIndexPre == NF_KEY_SS) + && (bHadDecSep // S, SS ',' + || (i>0 && nTypeArray[i-1] == NF_SYMBOLTYPE_STRING)); + // SS"any"00 take "any" as a valid decimal separator +} + + +xub_StrLen ImpSvNumberformatScan::ScanType(const String&) +{ + const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData(); + + xub_StrLen nPos = 0; + USHORT i = 0; + short eNewType; + BOOL bMatchBracket = FALSE; + bool bHaveGeneral = false; // if General/Standard encountered + + SkipStrings(i, nPos); + while (i < nAnzStrings) + { + if (nTypeArray[i] > 0) + { // keyword + switch (nTypeArray[i]) + { + case NF_KEY_E: // E + eNewType = NUMBERFORMAT_SCIENTIFIC; + break; + case NF_KEY_AMPM: // AM,A,PM,P + case NF_KEY_AP: + case NF_KEY_H: // H + case NF_KEY_HH: // HH + case NF_KEY_S: // S + case NF_KEY_SS: // SS + eNewType = NUMBERFORMAT_TIME; + break; + case NF_KEY_M: // M + case NF_KEY_MM: // MM + { // minute or month + USHORT nIndexPre = PreviousKeyword(i); + USHORT nIndexNex = NextKeyword(i); + sal_Unicode cChar = PreviousChar(i); + if (nIndexPre == NF_KEY_H || // H + nIndexPre == NF_KEY_HH || // HH + nIndexNex == NF_KEY_S || // S + nIndexNex == NF_KEY_SS || // SS + cChar == '[' ) // [M + { + eNewType = NUMBERFORMAT_TIME; + nTypeArray[i] -= 2; // 6 -> 4, 7 -> 5 + } + else + eNewType = NUMBERFORMAT_DATE; + } + break; + case NF_KEY_MMM: // MMM + case NF_KEY_MMMM: // MMMM + case NF_KEY_MMMMM: // MMMMM + case NF_KEY_Q: // Q + case NF_KEY_QQ: // QQ + case NF_KEY_D: // D + case NF_KEY_DD: // DD + case NF_KEY_DDD: // DDD + case NF_KEY_DDDD: // DDDD + case NF_KEY_YY: // YY + case NF_KEY_YYYY: // YYYY + case NF_KEY_NN: // NN + case NF_KEY_NNN: // NNN + case NF_KEY_NNNN: // NNNN + case NF_KEY_WW : // WW + case NF_KEY_AAA : // AAA + case NF_KEY_AAAA : // AAAA + case NF_KEY_EC : // E + case NF_KEY_EEC : // EE + case NF_KEY_G : // G + case NF_KEY_GG : // GG + case NF_KEY_GGG : // GGG + case NF_KEY_R : // R + case NF_KEY_RR : // RR + eNewType = NUMBERFORMAT_DATE; + break; + case NF_KEY_CCC: // CCC + eNewType = NUMBERFORMAT_CURRENCY; + break; + case NF_KEY_GENERAL: // Standard + eNewType = NUMBERFORMAT_NUMBER; + bHaveGeneral = true; + break; + default: + eNewType = NUMBERFORMAT_UNDEFINED; + break; + } + } + else + { // control character + switch ( sStrArray[i].GetChar(0) ) + { + case '#': + case '?': + eNewType = NUMBERFORMAT_NUMBER; + break; + case '0': + { + if ( (eScannedType & NUMBERFORMAT_TIME) == NUMBERFORMAT_TIME ) + { + if ( Is100SecZero( i, bDecSep ) ) + { + bDecSep = TRUE; // subsequent 0's + eNewType = NUMBERFORMAT_TIME; + } + else + return nPos; // Error + } + else + eNewType = NUMBERFORMAT_NUMBER; + } + break; + case '%': + eNewType = NUMBERFORMAT_PERCENT; + break; + case '/': + eNewType = NUMBERFORMAT_FRACTION; + break; + case '[': + { + if ( i < nAnzStrings-1 && + nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && + sStrArray[i+1].GetChar(0) == '$' ) + { // as of SV_NUMBERFORMATTER_VERSION_NEW_CURR + eNewType = NUMBERFORMAT_CURRENCY; + bMatchBracket = TRUE; + } + else if ( i < nAnzStrings-1 && + nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && + sStrArray[i+1].GetChar(0) == '~' ) + { // as of SV_NUMBERFORMATTER_VERSION_CALENDAR + eNewType = NUMBERFORMAT_DATE; + bMatchBracket = TRUE; + } + else + { + USHORT nIndexNex = NextKeyword(i); + if (nIndexNex == NF_KEY_H || // H + nIndexNex == NF_KEY_HH || // HH + nIndexNex == NF_KEY_M || // M + nIndexNex == NF_KEY_MM || // MM + nIndexNex == NF_KEY_S || // S + nIndexNex == NF_KEY_SS ) // SS + eNewType = NUMBERFORMAT_TIME; + else + return nPos; // Error + } + } + break; + case '@': + eNewType = NUMBERFORMAT_TEXT; + break; + default: + if ( sStrArray[i] == pLoc->getTime100SecSep() ) + bDecSep = TRUE; // for SS,0 + eNewType = NUMBERFORMAT_UNDEFINED; + break; + } + } + if (eScannedType == NUMBERFORMAT_UNDEFINED) + eScannedType = eNewType; + else if (eScannedType == NUMBERFORMAT_TEXT || eNewType == NUMBERFORMAT_TEXT) + eScannedType = NUMBERFORMAT_TEXT; // Text bleibt immer Text + else if (eNewType == NUMBERFORMAT_UNDEFINED) + { // bleibt wie bisher + } + else if (eScannedType != eNewType) + { + switch (eScannedType) + { + case NUMBERFORMAT_DATE: + { + switch (eNewType) + { + case NUMBERFORMAT_TIME: + eScannedType = NUMBERFORMAT_DATETIME; + break; + case NUMBERFORMAT_FRACTION: // DD/MM + break; + default: + { + if (nCurrPos != STRING_NOTFOUND) + eScannedType = NUMBERFORMAT_UNDEFINED; + else if ( sStrArray[i] != pFormatter->GetDateSep() ) + return nPos; + } + } + } + break; + case NUMBERFORMAT_TIME: + { + switch (eNewType) + { + case NUMBERFORMAT_DATE: + eScannedType = NUMBERFORMAT_DATETIME; + break; + case NUMBERFORMAT_FRACTION: // MM/SS + break; + default: + { + if (nCurrPos != STRING_NOTFOUND) + eScannedType = NUMBERFORMAT_UNDEFINED; + else if ( sStrArray[i] != pLoc->getTimeSep() ) + return nPos; + } + } + } + break; + case NUMBERFORMAT_DATETIME: + { + switch (eNewType) + { + case NUMBERFORMAT_TIME: + case NUMBERFORMAT_DATE: + break; + case NUMBERFORMAT_FRACTION: // DD/MM + break; + default: + { + if (nCurrPos != STRING_NOTFOUND) + eScannedType = NUMBERFORMAT_UNDEFINED; + else if ( sStrArray[i] != pFormatter->GetDateSep() + && sStrArray[i] != pLoc->getTimeSep() ) + return nPos; + } + } + } + break; + case NUMBERFORMAT_PERCENT: + { + switch (eNewType) + { + case NUMBERFORMAT_NUMBER: // nur Zahl nach Prozent + break; + default: + return nPos; + } + } + break; + case NUMBERFORMAT_SCIENTIFIC: + { + switch (eNewType) + { + case NUMBERFORMAT_NUMBER: // nur Zahl nach E + break; + default: + return nPos; + } + } + break; + case NUMBERFORMAT_NUMBER: + { + switch (eNewType) + { + case NUMBERFORMAT_SCIENTIFIC: + case NUMBERFORMAT_PERCENT: + case NUMBERFORMAT_FRACTION: + case NUMBERFORMAT_CURRENCY: + eScannedType = eNewType; + break; + default: + if (nCurrPos != STRING_NOTFOUND) + eScannedType = NUMBERFORMAT_UNDEFINED; + else + return nPos; + } + } + break; + case NUMBERFORMAT_FRACTION: + { + switch (eNewType) + { + case NUMBERFORMAT_NUMBER: // nur Zahl nach Bruch + break; + default: + return nPos; + } + } + break; + default: + break; + } + } + nPos = nPos + sStrArray[i].Len(); // Korrekturposition + i++; + if ( bMatchBracket ) + { // no type detection inside of matching brackets if [$...], [~...] + while ( bMatchBracket && i < nAnzStrings ) + { + if ( nTypeArray[i] == NF_SYMBOLTYPE_DEL + && sStrArray[i].GetChar(0) == ']' ) + bMatchBracket = FALSE; + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + if ( bMatchBracket ) + return nPos; // missing closing bracket at end of code + } + SkipStrings(i, nPos); + } + + if ((eScannedType == NUMBERFORMAT_NUMBER || eScannedType == NUMBERFORMAT_UNDEFINED) + && nCurrPos != STRING_NOTFOUND && !bHaveGeneral) + eScannedType = NUMBERFORMAT_CURRENCY; // old "automatic" currency + if (eScannedType == NUMBERFORMAT_UNDEFINED) + eScannedType = NUMBERFORMAT_DEFINED; + return 0; // Alles ok +} + + +bool ImpSvNumberformatScan::InsertSymbol( USHORT & nPos, svt::NfSymbolType eType, const String& rStr ) +{ + if (nAnzStrings >= NF_MAX_FORMAT_SYMBOLS || nPos > nAnzStrings) + return false; + ++nAnzResStrings; + if (nPos > 0 && nTypeArray[nPos-1] == NF_SYMBOLTYPE_EMPTY) + --nPos; // reuse position + else + { + ++nAnzStrings; + for (size_t i = nAnzStrings; i > nPos; --i) + { + nTypeArray[i] = nTypeArray[i-1]; + sStrArray[i] = sStrArray[i-1]; + } + } + nTypeArray[nPos] = static_cast<short>(eType); + sStrArray[nPos] = rStr; + return true; +} + + +int ImpSvNumberformatScan::FinalScanGetCalendar( xub_StrLen& nPos, USHORT& i, + USHORT& rAnzResStrings ) +{ + if ( sStrArray[i].GetChar(0) == '[' && + i < nAnzStrings-1 && + nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && + sStrArray[i+1].GetChar(0) == '~' ) + { // [~calendarID] + // as of SV_NUMBERFORMATTER_VERSION_CALENDAR + nPos = nPos + sStrArray[i].Len(); // [ + nTypeArray[i] = NF_SYMBOLTYPE_CALDEL; + nPos = nPos + sStrArray[++i].Len(); // ~ + sStrArray[i-1] += sStrArray[i]; // [~ + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + rAnzResStrings--; + if ( ++i >= nAnzStrings ) + return -1; // error + nPos = nPos + sStrArray[i].Len(); // calendarID + String& rStr = sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_CALENDAR; // convert + i++; + while ( i < nAnzStrings && + sStrArray[i].GetChar(0) != ']' ) + { + nPos = nPos + sStrArray[i].Len(); + rStr += sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + rAnzResStrings--; + i++; + } + if ( rStr.Len() && i < nAnzStrings && + sStrArray[i].GetChar(0) == ']' ) + { + nTypeArray[i] = NF_SYMBOLTYPE_CALDEL; + nPos = nPos + sStrArray[i].Len(); + i++; + } + else + return -1; // error + return 1; + } + return 0; +} + +xub_StrLen ImpSvNumberformatScan::FinalScan( String& rString, String& rComment ) +{ + const LocaleDataWrapper* pLoc = pFormatter->GetLocaleData(); + + // save values for convert mode + String sOldDecSep = pFormatter->GetNumDecimalSep(); + String sOldThousandSep = pFormatter->GetNumThousandSep(); + String sOldDateSep = pFormatter->GetDateSep(); + String sOldTimeSep = pLoc->getTimeSep(); + String sOldTime100SecSep= pLoc->getTime100SecSep(); + String sOldCurSymbol = GetCurSymbol(); + String sOldCurString = GetCurString(); + sal_Unicode cOldKeyH = sKeyword[NF_KEY_H].GetChar(0); + sal_Unicode cOldKeyMI = sKeyword[NF_KEY_MI].GetChar(0); + sal_Unicode cOldKeyS = sKeyword[NF_KEY_S].GetChar(0); + + // If the group separator is a Non-Breaking Space (French) continue with a + // normal space instead so queries on space work correctly. + // The format string is adjusted to allow both. + // For output of the format code string the LocaleData characters are used. + if ( sOldThousandSep.GetChar(0) == cNonBreakingSpace && sOldThousandSep.Len() == 1 ) + sOldThousandSep = ' '; + + // change locale data et al + if (bConvertMode) + { + pFormatter->ChangeIntl(eNewLnge); + //! pointer may have changed + pLoc = pFormatter->GetLocaleData(); + //! init new keywords + InitKeywords(); + } + const CharClass* pChrCls = pFormatter->GetCharClass(); + + xub_StrLen nPos = 0; // error correction position + USHORT i = 0; // symbol loop counter + USHORT nCounter = 0; // counts digits + nAnzResStrings = nAnzStrings; // counts remaining symbols + bDecSep = FALSE; // reset in case already used in TypeCheck + bool bThaiT = false; // Thai T NatNum modifier present + + switch (eScannedType) + { + case NUMBERFORMAT_TEXT: + case NUMBERFORMAT_DEFINED: + { + while (i < nAnzStrings) + { + switch (nTypeArray[i]) + { + case NF_SYMBOLTYPE_BLANK: + case NF_SYMBOLTYPE_STAR: + break; + case NF_SYMBOLTYPE_COMMENT: + { + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + SvNumberformat::EraseCommentBraces( rStr ); + rComment += rStr; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + break; + case NF_KEY_GENERAL : // #77026# "General" is the same as "@" + break; + default: + { + if ( nTypeArray[i] != NF_SYMBOLTYPE_DEL || + sStrArray[i].GetChar(0) != '@' ) + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + } + break; + } + nPos = nPos + sStrArray[i].Len(); + i++; + } // of while + } + break; + case NUMBERFORMAT_NUMBER: + case NUMBERFORMAT_PERCENT: + case NUMBERFORMAT_CURRENCY: + case NUMBERFORMAT_SCIENTIFIC: + case NUMBERFORMAT_FRACTION: + { + sal_Unicode cThousandFill = ' '; + while (i < nAnzStrings) + { + if (eScannedType == NUMBERFORMAT_FRACTION && // special case + nTypeArray[i] == NF_SYMBOLTYPE_DEL && // # ### #/# + StringEqualsChar( sOldThousandSep, ' ' ) && // e.g. France or Sweden + StringEqualsChar( sStrArray[i], ' ' ) && + !bFrac && + IsLastBlankBeforeFrac(i) ) + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; // del->string + } // kein Taus.p. + + + if (nTypeArray[i] == NF_SYMBOLTYPE_BLANK || + nTypeArray[i] == NF_SYMBOLTYPE_STAR || + nTypeArray[i] == NF_KEY_CCC || // CCC + nTypeArray[i] == NF_KEY_GENERAL ) // Standard + { + if (nTypeArray[i] == NF_KEY_GENERAL) + { + nThousand = FLAG_STANDARD_IN_FORMAT; + if ( bConvertMode ) + sStrArray[i] = sNameStandardFormat; + } + nPos = nPos + sStrArray[i].Len(); + i++; + } + else if (nTypeArray[i] == NF_SYMBOLTYPE_STRING || // Strings oder + nTypeArray[i] > 0) // Keywords + { + if (eScannedType == NUMBERFORMAT_SCIENTIFIC && + nTypeArray[i] == NF_KEY_E) // E+ + { + if (bExp) // doppelt + return nPos; + bExp = TRUE; + nExpPos = i; + if (bDecSep) + nCntPost = nCounter; + else + nCntPre = nCounter; + nCounter = 0; + nTypeArray[i] = NF_SYMBOLTYPE_EXP; + } + else if (eScannedType == NUMBERFORMAT_FRACTION && + sStrArray[i].GetChar(0) == ' ') + { + if (!bBlank && !bFrac) // nicht doppelt oder hinter / + { + if (bDecSep && nCounter > 0) // Nachkommastellen + return nPos; // Fehler + bBlank = TRUE; + nBlankPos = i; + nCntPre = nCounter; + nCounter = 0; + } + nTypeArray[i] = NF_SYMBOLTYPE_FRACBLANK; + } + else if (nTypeArray[i] == NF_KEY_THAI_T) + { + bThaiT = true; + sStrArray[i] = sKeyword[nTypeArray[i]]; + } + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + else if (nTypeArray[i] == NF_SYMBOLTYPE_DEL) + { + sal_Unicode cHere = sStrArray[i].GetChar(0); + // Handle not pre-known separators in switch. + sal_Unicode cSimplified; + if (StringEqualsChar( pFormatter->GetNumThousandSep(), cHere)) + cSimplified = ','; + else if (StringEqualsChar( pFormatter->GetNumDecimalSep(), cHere)) + cSimplified = '.'; + else + cSimplified = cHere; + switch ( cSimplified ) + { + case '#': + case '0': + case '?': + { + if (nThousand > 0) // #... # + return nPos; // Fehler + else if (bFrac && cHere == '0') + return nPos; // 0 im Nenner + nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + i++; + nCounter++; + while (i < nAnzStrings && + (sStrArray[i].GetChar(0) == '#' || + sStrArray[i].GetChar(0) == '0' || + sStrArray[i].GetChar(0) == '?') + ) + { + nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; + nPos = nPos + sStrArray[i].Len(); + nCounter++; + i++; + } + } + break; + case '-': + { + if ( bDecSep && nDecPos+1 == i && + nTypeArray[nDecPos] == NF_SYMBOLTYPE_DECSEP ) + { // "0.--" + nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + i++; + nCounter++; + while (i < nAnzStrings && + (sStrArray[i].GetChar(0) == '-') ) + { + // If more than two dashes are present in + // currency formats the last dash will be + // interpreted literally as a minus sign. + // Has to be this ugly. Period. + if ( eScannedType == NUMBERFORMAT_CURRENCY + && rStr.Len() >= 2 && + (i == nAnzStrings-1 || + sStrArray[i+1].GetChar(0) != '-') ) + break; + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + nCounter++; + i++; + } + } + else + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + } + break; + case '.': + case ',': + case '\'': + case ' ': + { + sal_Unicode cSep = cHere; // remember + if ( StringEqualsChar( sOldThousandSep, cSep ) ) + { + // previous char with skip empty + sal_Unicode cPre = PreviousChar(i); + sal_Unicode cNext; + if (bExp || bBlank || bFrac) + { // after E, / or ' ' + if ( !StringEqualsChar( sOldThousandSep, ' ' ) ) + { + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; // eat it + } + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + } + else if (i > 0 && i < nAnzStrings-1 && + (cPre == '#' || cPre == '0') && + ((cNext = NextChar(i)) == '#' || cNext == '0') + ) // #,# + { + nPos = nPos + sStrArray[i].Len(); + if (!bThousand) // only once + { + bThousand = TRUE; + cThousandFill = sStrArray[i+1].GetChar(0); + } + // Eat it, will be reinserted at proper + // grouping positions further down. + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + else if (i > 0 && (cPre == '#' || cPre == '0') + && PreviousType(i) == NF_SYMBOLTYPE_DIGIT + && nThousand < FLAG_STANDARD_IN_FORMAT ) + { // #,,,, + if ( StringEqualsChar( sOldThousandSep, ' ' ) ) + { // strange, those French.. + BOOL bFirst = TRUE; + String& rStr = sStrArray[i]; + // set a hard Non-Breaking Space or ConvertMode + const String& rSepF = pFormatter->GetNumThousandSep(); + while ( i < nAnzStrings + && sStrArray[i] == sOldThousandSep + && StringEqualsChar( sOldThousandSep, NextChar(i) ) ) + { // last was a space or another space + // is following => separator + nPos = nPos + sStrArray[i].Len(); + if ( bFirst ) + { + bFirst = FALSE; + rStr = rSepF; + nTypeArray[i] = NF_SYMBOLTYPE_THSEP; + } + else + { + rStr += rSepF; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + nThousand++; + i++; + } + if ( i < nAnzStrings-1 + && sStrArray[i] == sOldThousandSep ) + { // something following last space + // => space if currency contained, + // else separator + nPos = nPos + sStrArray[i].Len(); + if ( (nPos <= nCurrPos && + nCurrPos < nPos + sStrArray[i+1].Len()) + || nTypeArray[i+1] == NF_KEY_CCC + || (i < nAnzStrings-2 && + sStrArray[i+1].GetChar(0) == '[' && + sStrArray[i+2].GetChar(0) == '$') ) + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + } + else + { + if ( bFirst ) + { + bFirst = FALSE; + rStr = rSepF; + nTypeArray[i] = NF_SYMBOLTYPE_THSEP; + } + else + { + rStr += rSepF; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + nThousand++; + } + i++; + } + } + else + { + do + { + nThousand++; + nTypeArray[i] = NF_SYMBOLTYPE_THSEP; + nPos = nPos + sStrArray[i].Len(); + sStrArray[i] = pFormatter->GetNumThousandSep(); + i++; + } while (i < nAnzStrings && + sStrArray[i] == sOldThousandSep); + } + } + else // any grsep + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + i++; + while ( i < nAnzStrings && + sStrArray[i] == sOldThousandSep ) + { + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + } + } + else if ( StringEqualsChar( sOldDecSep, cSep ) ) + { + if (bBlank || bFrac) // . behind / or ' ' + return nPos; // error + else if (bExp) // behind E + { + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; // eat it + } + else if (bDecSep) // any . + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + i++; + while ( i < nAnzStrings && + sStrArray[i] == sOldDecSep ) + { + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + } + else + { + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_DECSEP; + sStrArray[i] = pFormatter->GetNumDecimalSep(); + bDecSep = TRUE; + nDecPos = i; + nCntPre = nCounter; + nCounter = 0; + + i++; + } + } // of else = DecSep + else // . without meaning + { + if (cSep == ' ' && + eScannedType == NUMBERFORMAT_FRACTION && + StringEqualsChar( sStrArray[i], ' ' ) ) + { + if (!bBlank && !bFrac) // no dups + { // or behind / + if (bDecSep && nCounter > 0)// dec. + return nPos; // error + bBlank = TRUE; + nBlankPos = i; + nCntPre = nCounter; + nCounter = 0; + } + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + } + else + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + i++; + while (i < nAnzStrings && + StringEqualsChar( sStrArray[i], cSep ) ) + { + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + } + } + } + break; + case '/': + { + if (eScannedType == NUMBERFORMAT_FRACTION) + { + if ( i == 0 || + (nTypeArray[i-1] != NF_SYMBOLTYPE_DIGIT && + nTypeArray[i-1] != NF_SYMBOLTYPE_EMPTY) ) + return nPos ? nPos : 1; // /? not allowed + else if (!bFrac || (bDecSep && nCounter > 0)) + { + bFrac = TRUE; + nCntPost = nCounter; + nCounter = 0; + nTypeArray[i] = NF_SYMBOLTYPE_FRAC; + nPos = nPos + sStrArray[i].Len(); + i++; + } + else // / doppelt od. , imZaehl + return nPos; // Fehler + } + else + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + } + break; + case '[' : + { + if ( eScannedType == NUMBERFORMAT_CURRENCY && + i < nAnzStrings-1 && + nTypeArray[i+1] == NF_SYMBOLTYPE_STRING && + sStrArray[i+1].GetChar(0) == '$' ) + { // [$DM-xxx] + // ab SV_NUMBERFORMATTER_VERSION_NEW_CURR + nPos = nPos + sStrArray[i].Len(); // [ + nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL; + nPos = nPos + sStrArray[++i].Len(); // $ + sStrArray[i-1] += sStrArray[i]; // [$ + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + if ( ++i >= nAnzStrings ) + return nPos; // Fehler + nPos = nPos + sStrArray[i].Len(); // DM + String& rStr = sStrArray[i]; + String* pStr = &sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_CURRENCY; // wandeln + BOOL bHadDash = FALSE; + i++; + while ( i < nAnzStrings && + sStrArray[i].GetChar(0) != ']' ) + { + nPos = nPos + sStrArray[i].Len(); + if ( bHadDash ) + { + *pStr += sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + else + { + if ( sStrArray[i].GetChar(0) == '-' ) + { + bHadDash = TRUE; + pStr = &sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_CURREXT; + } + else + { + *pStr += sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + } + i++; + } + if ( rStr.Len() && i < nAnzStrings && + sStrArray[i].GetChar(0) == ']' ) + { + nTypeArray[i] = NF_SYMBOLTYPE_CURRDEL; + nPos = nPos + sStrArray[i].Len(); + i++; + } + else + return nPos; // Fehler + } + else + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + } + break; + default: // andere Dels + { + if (eScannedType == NUMBERFORMAT_PERCENT && + cHere == '%') + nTypeArray[i] = NF_SYMBOLTYPE_PERCENT; + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + } // of switch (Del) + } // of else Del + else if ( nTypeArray[i] == NF_SYMBOLTYPE_COMMENT ) + { + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + SvNumberformat::EraseCommentBraces( rStr ); + rComment += rStr; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + else + { + DBG_ERRORFILE( "unknown NF_SYMBOLTYPE_..." ); + nPos = nPos + sStrArray[i].Len(); + i++; + } + } // of while + if (eScannedType == NUMBERFORMAT_FRACTION) + { + if (bFrac) + nCntExp = nCounter; + else if (bBlank) + nCntPost = nCounter; + else + nCntPre = nCounter; + } + else + { + if (bExp) + nCntExp = nCounter; + else if (bDecSep) + nCntPost = nCounter; + else + nCntPre = nCounter; + } + if (bThousand) // Expansion of grouping separators + { + USHORT nMaxPos; + if (bFrac) + { + if (bBlank) + nMaxPos = nBlankPos; + else + nMaxPos = 0; // no grouping + } + else if (bDecSep) // decimal separator present + nMaxPos = nDecPos; + else if (bExp) // 'E' exponent present + nMaxPos = nExpPos; + else // up to end + nMaxPos = i; + // Insert separators at proper positions. + xub_StrLen nCount = 0; + utl::DigitGroupingIterator aGrouping( pLoc->getDigitGrouping()); + size_t nFirstDigitSymbol = nMaxPos; + size_t nFirstGroupingSymbol = nMaxPos; + i = nMaxPos; + while (i-- > 0) + { + if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) + { + nFirstDigitSymbol = i; + nCount = nCount + sStrArray[i].Len(); // MSC converts += to int and then warns, so ... + // Insert separator only if not leftmost symbol. + if (i > 0 && nCount >= aGrouping.getPos()) + { + DBG_ASSERT( sStrArray[i].Len() == 1, + "ImpSvNumberformatScan::FinalScan: combined digits in group separator insertion"); + if (!InsertSymbol( i, NF_SYMBOLTYPE_THSEP, + pFormatter->GetNumThousandSep())) + // nPos isn't correct here, but signals error + return nPos; + // i may have been decremented by 1 + nFirstDigitSymbol = i + 1; + nFirstGroupingSymbol = i; + aGrouping.advance(); + } + } + } + // Generated something like "string",000; remove separator again. + if (nFirstGroupingSymbol < nFirstDigitSymbol) + { + nTypeArray[nFirstGroupingSymbol] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + } + // Combine digits into groups to save memory (Info will be copied + // later, taking only non-empty symbols). + for (i = 0; i < nAnzStrings; ++i) + { + if (nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) + { + String& rStr = sStrArray[i]; + while (++i < nAnzStrings && + nTypeArray[i] == NF_SYMBOLTYPE_DIGIT) + { + rStr += sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + } + } + } + break; // of NUMBERFORMAT_NUMBER + case NUMBERFORMAT_DATE: + { + while (i < nAnzStrings) + { + switch (nTypeArray[i]) + { + case NF_SYMBOLTYPE_BLANK: + case NF_SYMBOLTYPE_STAR: + case NF_SYMBOLTYPE_STRING: + nPos = nPos + sStrArray[i].Len(); + i++; + break; + case NF_SYMBOLTYPE_COMMENT: + { + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + SvNumberformat::EraseCommentBraces( rStr ); + rComment += rStr; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + break; + case NF_SYMBOLTYPE_DEL: + { + int nCalRet; + if (sStrArray[i] == sOldDateSep) + { + nTypeArray[i] = NF_SYMBOLTYPE_DATESEP; + nPos = nPos + sStrArray[i].Len(); + if (bConvertMode) + sStrArray[i] = pFormatter->GetDateSep(); + i++; + } + else if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 ) + { + if ( nCalRet < 0 ) + return nPos; // error + } + else + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + } + break; + case NF_KEY_THAI_T : + bThaiT = true; + // fall thru + case NF_KEY_M: // M + case NF_KEY_MM: // MM + case NF_KEY_MMM: // MMM + case NF_KEY_MMMM: // MMMM + case NF_KEY_MMMMM: // MMMMM + case NF_KEY_Q: // Q + case NF_KEY_QQ: // QQ + case NF_KEY_D: // D + case NF_KEY_DD: // DD + case NF_KEY_DDD: // DDD + case NF_KEY_DDDD: // DDDD + case NF_KEY_YY: // YY + case NF_KEY_YYYY: // YYYY + case NF_KEY_NN: // NN + case NF_KEY_NNN: // NNN + case NF_KEY_NNNN: // NNNN + case NF_KEY_WW : // WW + case NF_KEY_AAA : // AAA + case NF_KEY_AAAA : // AAAA + case NF_KEY_EC : // E + case NF_KEY_EEC : // EE + case NF_KEY_G : // G + case NF_KEY_GG : // GG + case NF_KEY_GGG : // GGG + case NF_KEY_R : // R + case NF_KEY_RR : // RR + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + break; + default: // andere Keywords + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + break; + } + } // of while + } + break; // of NUMBERFORMAT_DATE + case NUMBERFORMAT_TIME: + { + while (i < nAnzStrings) + { + switch (nTypeArray[i]) + { + case NF_SYMBOLTYPE_BLANK: + case NF_SYMBOLTYPE_STAR: + { + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + case NF_SYMBOLTYPE_DEL: + { + switch( sStrArray[i].GetChar(0) ) + { + case '0': + { + if ( Is100SecZero( i, bDecSep ) ) + { + bDecSep = TRUE; + nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; + String& rStr = sStrArray[i]; + i++; + nPos = nPos + sStrArray[i].Len(); + nCounter++; + while (i < nAnzStrings && + sStrArray[i].GetChar(0) == '0') + { + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + nCounter++; + i++; + } + } + else + return nPos; + } + break; + case '#': + case '?': + return nPos; + case '[': + { + if (bThousand) // doppelt + return nPos; + bThousand = TRUE; // bei Time frei + sal_Unicode cChar = pChrCls->upper( NextChar(i) ).GetChar(0); + if ( cChar == cOldKeyH ) + nThousand = 1; // H + else if ( cChar == cOldKeyMI ) + nThousand = 2; // M + else if ( cChar == cOldKeyS ) + nThousand = 3; // S + else + return nPos; + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + case ']': + { + if (!bThousand) // kein [ vorher + return nPos; + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + default: + { + nPos = nPos + sStrArray[i].Len(); + if ( sStrArray[i] == sOldTimeSep ) + { + nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP; + if ( bConvertMode ) + sStrArray[i] = pLoc->getTimeSep(); + } + else if ( sStrArray[i] == sOldTime100SecSep ) + { + bDecSep = TRUE; + nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP; + if ( bConvertMode ) + sStrArray[i] = pLoc->getTime100SecSep(); + } + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + i++; + } + break; + } + } + break; + case NF_SYMBOLTYPE_STRING: + { + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + case NF_SYMBOLTYPE_COMMENT: + { + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + SvNumberformat::EraseCommentBraces( rStr ); + rComment += rStr; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + break; + case NF_KEY_AMPM: // AM/PM + case NF_KEY_AP: // A/P + { + bExp = TRUE; // missbraucht fuer A/P + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + case NF_KEY_THAI_T : + bThaiT = true; + // fall thru + case NF_KEY_MI: // M + case NF_KEY_MMI: // MM + case NF_KEY_H: // H + case NF_KEY_HH: // HH + case NF_KEY_S: // S + case NF_KEY_SS: // SS + { + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + default: // andere Keywords + { + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + } + } // of while + nCntPost = nCounter; // Zaehler der Nullen + if (bExp) + nCntExp = 1; // merkt AM/PM + } + break; // of NUMBERFORMAT_TIME + case NUMBERFORMAT_DATETIME: + { + BOOL bTimePart = FALSE; + while (i < nAnzStrings) + { + switch (nTypeArray[i]) + { + case NF_SYMBOLTYPE_BLANK: + case NF_SYMBOLTYPE_STAR: + case NF_SYMBOLTYPE_STRING: + nPos = nPos + sStrArray[i].Len(); + i++; + break; + case NF_SYMBOLTYPE_COMMENT: + { + String& rStr = sStrArray[i]; + nPos = nPos + rStr.Len(); + SvNumberformat::EraseCommentBraces( rStr ); + rComment += rStr; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + i++; + } + break; + case NF_SYMBOLTYPE_DEL: + { + int nCalRet; + if ( (nCalRet = FinalScanGetCalendar( nPos, i, nAnzResStrings )) != 0 ) + { + if ( nCalRet < 0 ) + return nPos; // error + } + else + { + switch( sStrArray[i].GetChar(0) ) + { + case '0': + { + if ( bTimePart && Is100SecZero( i, bDecSep ) ) + { + bDecSep = TRUE; + nTypeArray[i] = NF_SYMBOLTYPE_DIGIT; + String& rStr = sStrArray[i]; + i++; + nPos = nPos + sStrArray[i].Len(); + nCounter++; + while (i < nAnzStrings && + sStrArray[i].GetChar(0) == '0') + { + rStr += sStrArray[i]; + nPos = nPos + sStrArray[i].Len(); + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + nCounter++; + i++; + } + } + else + return nPos; + } + break; + case '#': + case '?': + return nPos; + default: + { + nPos = nPos + sStrArray[i].Len(); + if (bTimePart) + { + if ( sStrArray[i] == sOldTimeSep ) + { + nTypeArray[i] = NF_SYMBOLTYPE_TIMESEP; + if ( bConvertMode ) + sStrArray[i] = pLoc->getTimeSep(); + } + else if ( sStrArray[i] == sOldTime100SecSep ) + { + bDecSep = TRUE; + nTypeArray[i] = NF_SYMBOLTYPE_TIME100SECSEP; + if ( bConvertMode ) + sStrArray[i] = pLoc->getTime100SecSep(); + } + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + } + else + { + if ( sStrArray[i] == sOldDateSep ) + { + nTypeArray[i] = NF_SYMBOLTYPE_DATESEP; + if (bConvertMode) + sStrArray[i] = pFormatter->GetDateSep(); + } + else + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + } + i++; + } + } + } + } + break; + case NF_KEY_AMPM: // AM/PM + case NF_KEY_AP: // A/P + { + bTimePart = TRUE; + bExp = TRUE; // missbraucht fuer A/P + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + } + break; + case NF_KEY_MI: // M + case NF_KEY_MMI: // MM + case NF_KEY_H: // H + case NF_KEY_HH: // HH + case NF_KEY_S: // S + case NF_KEY_SS: // SS + bTimePart = TRUE; + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + break; + case NF_KEY_M: // M + case NF_KEY_MM: // MM + case NF_KEY_MMM: // MMM + case NF_KEY_MMMM: // MMMM + case NF_KEY_MMMMM: // MMMMM + case NF_KEY_Q: // Q + case NF_KEY_QQ: // QQ + case NF_KEY_D: // D + case NF_KEY_DD: // DD + case NF_KEY_DDD: // DDD + case NF_KEY_DDDD: // DDDD + case NF_KEY_YY: // YY + case NF_KEY_YYYY: // YYYY + case NF_KEY_NN: // NN + case NF_KEY_NNN: // NNN + case NF_KEY_NNNN: // NNNN + case NF_KEY_WW : // WW + case NF_KEY_AAA : // AAA + case NF_KEY_AAAA : // AAAA + case NF_KEY_EC : // E + case NF_KEY_EEC : // EE + case NF_KEY_G : // G + case NF_KEY_GG : // GG + case NF_KEY_GGG : // GGG + case NF_KEY_R : // R + case NF_KEY_RR : // RR + bTimePart = FALSE; + sStrArray[i] = sKeyword[nTypeArray[i]]; // tTtT -> TTTT + nPos = nPos + sStrArray[i].Len(); + i++; + break; + case NF_KEY_THAI_T : + bThaiT = true; + sStrArray[i] = sKeyword[nTypeArray[i]]; + nPos = nPos + sStrArray[i].Len(); + i++; + break; + default: // andere Keywords + nTypeArray[i] = NF_SYMBOLTYPE_STRING; + nPos = nPos + sStrArray[i].Len(); + i++; + break; + } + } // of while + nCntPost = nCounter; // decimals (100th seconds) + if (bExp) + nCntExp = 1; // merkt AM/PM + } + break; // of NUMBERFORMAT_DATETIME + default: + break; + } + if (eScannedType == NUMBERFORMAT_SCIENTIFIC && + (nCntPre + nCntPost == 0 || nCntExp == 0)) + return nPos; + else if (eScannedType == NUMBERFORMAT_FRACTION && (nCntExp > 8 || nCntExp == 0)) + return nPos; + + if (bThaiT && !GetNatNumModifier()) + SetNatNumModifier(1); + + if ( bConvertMode ) + { // strings containing keywords of the target locale must be quoted, so + // the user sees the difference and is able to edit the format string + for ( i=0; i < nAnzStrings; i++ ) + { + if ( nTypeArray[i] == NF_SYMBOLTYPE_STRING && + sStrArray[i].GetChar(0) != '\"' ) + { + if ( bConvertSystemToSystem && eScannedType == NUMBERFORMAT_CURRENCY ) + { // don't stringize automatic currency, will be converted + if ( sStrArray[i] == sOldCurSymbol ) + continue; // for + // DM might be splitted into D and M + if ( sStrArray[i].Len() < sOldCurSymbol.Len() && + pChrCls->toUpper( sStrArray[i], 0, 1 ).GetChar(0) == + sOldCurString.GetChar(0) ) + { + String aTmp( sStrArray[i] ); + USHORT j = i + 1; + while ( aTmp.Len() < sOldCurSymbol.Len() && + j < nAnzStrings && + nTypeArray[j] == NF_SYMBOLTYPE_STRING ) + { + aTmp += sStrArray[j++]; + } + if ( pChrCls->upper( aTmp ) == sOldCurString ) + { + sStrArray[i++] = aTmp; + for ( ; i<j; i++ ) + { + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + i = j - 1; + continue; // for + } + } + } + String& rStr = sStrArray[i]; + xub_StrLen nLen = rStr.Len(); + for ( xub_StrLen j=0; j<nLen; j++ ) + { + if ( (j == 0 || rStr.GetChar(j-1) != '\\') && GetKeyWord( rStr, j ) ) + { + rStr.Insert( '\"', 0 ); + rStr += '\"'; + break; // for + } + } + } + } + } + // concatenate strings, remove quotes for output, and rebuild the format string + rString.Erase(); + i = 0; + while (i < nAnzStrings) + { + switch ( nTypeArray[i] ) + { + case NF_SYMBOLTYPE_STRING : + { + xub_StrLen nStringPos = rString.Len(); + xub_StrLen nArrPos = 0; + USHORT iPos = i; + do + { + if (sStrArray[i].Len() == 2 && + sStrArray[i].GetChar(0) == '\\') + { + // Unescape some simple forms of symbols even in the UI + // visible string to prevent duplicates that differ + // only in notation, originating from import. + // e.g. YYYY-MM-DD and YYYY\-MM\-DD are identical, + // but 0\ 000 0 and 0 000 0 in a French locale are not. + sal_Unicode c = sStrArray[i].GetChar(1); + switch (c) + { + case '+': + case '-': + rString += c; + break; + case ' ': + case '.': + case '/': + if (((eScannedType & NUMBERFORMAT_DATE) == 0) + && (StringEqualsChar( + pFormatter->GetNumThousandSep(), + c) || StringEqualsChar( + pFormatter->GetNumDecimalSep(), + c) || (c == ' ' && + StringEqualsChar( + pFormatter->GetNumThousandSep(), + cNonBreakingSpace)))) + rString += sStrArray[i]; + else if ((eScannedType & NUMBERFORMAT_DATE) && + StringEqualsChar( + pFormatter->GetDateSep(), c)) + rString += sStrArray[i]; + else if ((eScannedType & NUMBERFORMAT_TIME) && + (StringEqualsChar( pLoc->getTimeSep(), + c) || + StringEqualsChar( + pLoc->getTime100SecSep(), c))) + rString += sStrArray[i]; + else if (eScannedType & NUMBERFORMAT_FRACTION) + rString += sStrArray[i]; + else + rString += c; + break; + default: + rString += sStrArray[i]; + } + } + else + rString += sStrArray[i]; + if ( RemoveQuotes( sStrArray[i] ) > 0 ) + { // update currency up to quoted string + if ( eScannedType == NUMBERFORMAT_CURRENCY ) + { // dM -> DM or DM -> $ in old automatic + // currency formats, oh my ..., why did we ever + // introduce them? + String aTmp( pChrCls->toUpper( + sStrArray[iPos], nArrPos, + sStrArray[iPos].Len()-nArrPos ) ); + xub_StrLen nCPos = aTmp.Search( sOldCurString ); + if ( nCPos != STRING_NOTFOUND ) + { + const String& rCur = + bConvertMode && bConvertSystemToSystem ? + GetCurSymbol() : sOldCurSymbol; + sStrArray[iPos].Replace( nArrPos+nCPos, + sOldCurString.Len(), rCur ); + rString.Replace( nStringPos+nCPos, + sOldCurString.Len(), rCur ); + } + nStringPos = rString.Len(); + if ( iPos == i ) + nArrPos = sStrArray[iPos].Len(); + else + nArrPos = sStrArray[iPos].Len() + sStrArray[i].Len(); + } + } + if ( iPos != i ) + { + sStrArray[iPos] += sStrArray[i]; + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + i++; + } while ( i < nAnzStrings && nTypeArray[i] == NF_SYMBOLTYPE_STRING ); + if ( i < nAnzStrings ) + i--; // enter switch on next symbol again + if ( eScannedType == NUMBERFORMAT_CURRENCY && nStringPos < rString.Len() ) + { // same as above, since last RemoveQuotes + String aTmp( pChrCls->toUpper( + sStrArray[iPos], nArrPos, + sStrArray[iPos].Len()-nArrPos ) ); + xub_StrLen nCPos = aTmp.Search( sOldCurString ); + if ( nCPos != STRING_NOTFOUND ) + { + const String& rCur = + bConvertMode && bConvertSystemToSystem ? + GetCurSymbol() : sOldCurSymbol; + sStrArray[iPos].Replace( nArrPos+nCPos, + sOldCurString.Len(), rCur ); + rString.Replace( nStringPos+nCPos, + sOldCurString.Len(), rCur ); + } + } + } + break; + case NF_SYMBOLTYPE_CURRENCY : + { + rString += sStrArray[i]; + RemoveQuotes( sStrArray[i] ); + } + break; + case NF_KEY_THAI_T: + if (bThaiT && GetNatNumModifier() == 1) + { // Remove T from format code, will be replaced with a [NatNum1] prefix. + nTypeArray[i] = NF_SYMBOLTYPE_EMPTY; + nAnzResStrings--; + } + else + rString += sStrArray[i]; + break; + case NF_SYMBOLTYPE_EMPTY : + // nothing + break; + default: + rString += sStrArray[i]; + } + i++; + } + return 0; +} + + +xub_StrLen ImpSvNumberformatScan::RemoveQuotes( String& rStr ) +{ + if ( rStr.Len() > 1 ) + { + sal_Unicode c = rStr.GetChar(0); + xub_StrLen n; + if ( c == '"' && rStr.GetChar( (n = xub_StrLen(rStr.Len()-1)) ) == '"' ) + { + rStr.Erase(n,1); + rStr.Erase(0,1); + return 2; + } + else if ( c == '\\' ) + { + rStr.Erase(0,1); + return 1; + } + } + return 0; +} + + +xub_StrLen ImpSvNumberformatScan::ScanFormat( String& rString, String& rComment ) +{ + xub_StrLen res = Symbol_Division(rString); //lexikalische Analyse + if (!res) + res = ScanType(rString); // Erkennung des Formattyps + if (!res) + res = FinalScan( rString, rComment ); // Typabhaengige Endanalyse + return res; // res = Kontrollposition + // res = 0 => Format ok +} + +void ImpSvNumberformatScan::CopyInfo(ImpSvNumberformatInfo* pInfo, USHORT nAnz) +{ + size_t i,j; + j = 0; + i = 0; + while (i < nAnz && j < NF_MAX_FORMAT_SYMBOLS) + { + if (nTypeArray[j] != NF_SYMBOLTYPE_EMPTY) + { + pInfo->sStrArray[i] = sStrArray[j]; + pInfo->nTypeArray[i] = nTypeArray[j]; + i++; + } + j++; + } + pInfo->eScannedType = eScannedType; + pInfo->bThousand = bThousand; + pInfo->nThousand = nThousand; + pInfo->nCntPre = nCntPre; + pInfo->nCntPost = nCntPost; + pInfo->nCntExp = nCntExp; +} + + |