/*************************************************************************
 *
 *  $RCSfile: zformat.hxx,v $
 *
 *  $Revision: 1.19.6.1 $
 *
 *  last change: $Author: mh $ $Date: 2002/10/31 20:37:02 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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 for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _ZFORMAT_HXX
#define _ZFORMAT_HXX

#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#ifndef _LANG_HXX //autogen
#include <tools/lang.hxx>
#endif
#ifndef _INTN_HXX //autogen
#include <tools/intn.hxx>
#endif

#include <svtools/zforlist.hxx>
#include <svtools/nfversi.hxx>

//! For ImpSvNumberformatScan: first the short symbols, then the long symbols!
//! e.g. first TT then TTTT
//! The internal order is essentially for the format code string scanner!
//! New keywords MUST NOT be inserted, only the NF_KEY_UNUSEDn may be used,
//! NF_KEY_LASTKEYWORD must be adjusted accordingly. Otherwise old versions
//! will fail upon reading these entries. Nevertheless, old versions are NOT
//! able to display those new keywords => blank display.
//
// ER 15.12.99: This table is externally only to be used with method
// String SvNumberformat::GetMappedFormatstring( const NfKeywordTable&, const LocaleDataWrapper& );
enum NfKeywordIndex
{
	NF_KEY_NONE = 0,
	NF_KEY_E,			// exponential symbol
	NF_KEY_AMPM,		// AM/PM
	NF_KEY_AP,			// a/p
	NF_KEY_MI,			// minute		(!)
	NF_KEY_MMI,			// minute 02	(!)
	NF_KEY_M,			// month		(!)
	NF_KEY_MM,			// month 02		(!)
	NF_KEY_MMM,			// month short name
	NF_KEY_MMMM,		// month long name
	NF_KEY_H,			// hour
	NF_KEY_HH,			// hour 02
	NF_KEY_S,			// second
	NF_KEY_SS,			// second 02
	NF_KEY_Q,			// quarter
	NF_KEY_QQ,			// quarter 02
	NF_KEY_D,			// day of month
	NF_KEY_DD,			// day of month 02
	NF_KEY_DDD,			// day of week short
	NF_KEY_DDDD,		// day of week long
	NF_KEY_YY,			// year two digits
	NF_KEY_YYYY,		// year four digits
	NF_KEY_NN,			// day of week short
	NF_KEY_NNNN,		// day of week long with separator
	NF_KEY_CCC,			// currency bank symbol (old version)
	NF_KEY_GENERAL,		// General / Standard
	NF_KEY_LASTOLDKEYWORD = NF_KEY_GENERAL,
	NF_KEY_NNN,			// day of week long without separator, as of version 6, 10.10.97
	NF_KEY_WW,			// week of year, as of version 8, 19.06.98
	NF_KEY_MMMMM,		// first letter of month name
	NF_KEY_LASTKEYWORD = NF_KEY_MMMMM,
	NF_KEY_UNUSED4,
    NF_KEY_QUARTER,     // was quarter word, not used anymore from SRC631 on (26.04.01)
	NF_KEY_TRUE,		// boolean true
	NF_KEY_FALSE,		// boolean false
	NF_KEY_BOOLEAN,		// boolean
	NF_KEY_COLOR,		// color
	NF_KEY_FIRSTCOLOR,
	NF_KEY_BLACK = NF_KEY_FIRSTCOLOR,	// you do know colors, don't you?
	NF_KEY_BLUE,
	NF_KEY_GREEN,
	NF_KEY_CYAN,
	NF_KEY_RED,
	NF_KEY_MAGENTA,
	NF_KEY_BROWN,
	NF_KEY_GREY,
	NF_KEY_YELLOW,
	NF_KEY_WHITE,
	NF_KEY_LASTCOLOR = NF_KEY_WHITE,
	NF_KEY_LASTKEYWORD_SO5 = NF_KEY_LASTCOLOR,
	//! Keys from here on can't be saved in SO5 file format and MUST be
	//! converted to string which means losing any information.
	NF_KEY_AAA,			// abbreviated day name from Japanese Xcl, same as DDD or NN English
	NF_KEY_AAAA,		// full day name from Japanese Xcl, same as DDDD or NNN English
	NF_KEY_EC,			// E non-gregorian calendar year without preceding 0
	NF_KEY_EEC,			// EE non-gregorian calendar year with preceding 0 (two digit)
	NF_KEY_G,			// abbreviated era name, latin characters M T S or H for Gengou calendar
	NF_KEY_GG,			// abbreviated era name
	NF_KEY_GGG,			// full era name
	NF_KEY_R,			// acts as EE (Xcl) => GR==GEE, GGR==GGEE, GGGR==GGGEE
	NF_KEY_RR,			// acts as GGGEE (Xcl)
	NF_KEYWORD_ENTRIES_COUNT
};

typedef String NfKeywordTable [NF_KEYWORD_ENTRIES_COUNT];

// This is a bit twisted because zforscan.hxx includes zformat.hxx again but
// does not need anything else than the typedef above. But in case of the
// private SvNumberformat definitions we need ImpSvNumberformatScan.
#ifdef _ZFORMAT_CXX
#include "zforscan.hxx"
#endif

// If comment field is also in format code string, was used for SUPD versions 371-372
#if SUPD < 372
#define NF_COMMENT_IN_FORMATSTRING 1
#else
#define NF_COMMENT_IN_FORMATSTRING 0
#endif

class SvStream;
class Color;

class ImpSvNumberformatScan;			// format code string scanner
class ImpSvNumberInputScan;				// input string scanner
class ImpSvNumMultipleWriteHeader;		// compatible file format
class ImpSvNumMultipleReadHeader;		// compatible file format
class SvNumberFormatter;

enum SvNumberformatLimitOps
{
	NUMBERFORMAT_OP_NO  = 0,			// Undefined, no OP
	NUMBERFORMAT_OP_EQ  = 1, 			// Operator =
	NUMBERFORMAT_OP_NE  = 2,			// Operator <>
	NUMBERFORMAT_OP_LT  = 3,			// Operator <
	NUMBERFORMAT_OP_LE  = 4,			// Operator <=
	NUMBERFORMAT_OP_GT  = 5,			// Operator >
	NUMBERFORMAT_OP_GE  = 6				// Operator >=
};

// SYSTEM-german to SYSTEM-xxx and vice versa conversion hack onLoad
enum NfHackConversion
{
	NF_CONVERT_NONE,
	NF_CONVERT_GERMAN_ENGLISH,
	NF_CONVERT_ENGLISH_GERMAN
};

struct ImpSvNumberformatInfo           	// Struct for FormatInfo
{
	String* sStrArray;					// Array of symbols
	short* nTypeArray;					// Array of infos
	USHORT nThousand;					// Count of group separator sequences
	USHORT nCntPre;						// Count of digits before decimal point
	USHORT nCntPost;					// Count of digits after decimal point
	USHORT nCntExp;					   	// Count of exponent digits, or AM/PM
	short eScannedType;					// Type determined by scan
	BOOL bThousand;						// Has group (AKA thousand) separator

	void Copy( const ImpSvNumberformatInfo& rNumFor, USHORT nAnz );
	void Load(SvStream& rStream, USHORT nAnz);
	void Save(SvStream& rStream, USHORT nAnz) const;
};

// DoubleByteNumber, represent numbers using Chinese or other digits if nNum>0,
// eLang specifies the Locale to use.
struct SvNumberDBNum
{
	LanguageType	eLang;
	BYTE			nNum;

					SvNumberDBNum() : eLang( LANGUAGE_DONTKNOW ), nNum(0) {}
	BOOL			IsComplete() const { return nNum && eLang != LANGUAGE_DONTKNOW; }
};

class CharClass;

class ImpSvNumFor						// One of four subformats of the format code string
{
public:
	ImpSvNumFor();						// Ctor without filling the Info
	~ImpSvNumFor();

	void Enlarge(USHORT nAnz);			// Init of arrays to the right size
	void Load( SvStream& rStream, ImpSvNumberformatScan& rSc,
				String& rLoadedColorName);
	void Save( SvStream& rStream ) const;

	void Copy( const ImpSvNumFor& rNumFor );

	// Access to Info; call Enlarge before!
	ImpSvNumberformatInfo& Info() { return aI;}
	const ImpSvNumberformatInfo& Info() const { return aI; }

	// Get count of substrings (symbols)
	USHORT GetnAnz() const { return nAnzStrings;}

	Color* GetColor() const { return pColor; }
	void SetColor( Color* pCol, String& rName )
	 { pColor = pCol; sColorName = rName; }
	const String& GetColorName() const { return sColorName; }

	// new SYMBOLTYPE_CURRENCY in subformat?
	BOOL HasNewCurrency() const;
	BOOL GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const;
	void SaveNewCurrencyMap( SvStream& rStream ) const;
	void LoadNewCurrencyMap( SvStream& rStream );

	// [DBNum1], [DBNum2], ...
	void SetDBNumNum( BYTE nNum ) { aDBNum.nNum = nNum; }
	void SetDBNumLang( LanguageType eLang ) { aDBNum.eLang = eLang; }
	const SvNumberDBNum& GetDBNum() const { return aDBNum; }

private:
	ImpSvNumberformatInfo aI;			// Hilfsstruct fuer die restlichen Infos
	String sColorName;					// color name
	Color* pColor;						// pointer to color of subformat
	USHORT nAnzStrings;					// count of symbols
	SvNumberDBNum aDBNum;				// DoubleByteNumber

};

class SvNumberformat
{
public:
	// Ctor for Load
	SvNumberformat( ImpSvNumberformatScan& rSc, LanguageType eLge );

	// Normal ctor
	SvNumberformat( String& rString,
				   ImpSvNumberformatScan* pSc,
				   ImpSvNumberInputScan* pISc,
				   xub_StrLen& nCheckPos,
				   LanguageType& eLan,
				   BOOL bStand = FALSE );

	// Copy ctor
	SvNumberformat( SvNumberformat& rFormat );

	// Copy ctor with exchange of format code string scanner (used in merge)
	SvNumberformat( SvNumberformat& rFormat, ImpSvNumberformatScan& rSc );

	~SvNumberformat();

	/// Get type of format, may include NUMBERFORMAT_DEFINED bit
	short GetType() const
		{ return (nNewStandardDefined &&
			(nNewStandardDefined <= SV_NUMBERFORMATTER_VERSION)) ?
			(eType & ~NUMBERFORMAT_DEFINED) : eType; }

	void SetType(const short eSetType)          { eType = eSetType; }
	// Standard means the I18N defined standard format of this type
	void SetStandard()                          { bStandard = TRUE; }
	BOOL IsStandard() const						{ return bStandard; }

	// For versions before version nVer it is UserDefined, for newer versions
	// it is builtin. nVer of SV_NUMBERFORMATTER_VERSION_...
	void SetNewStandardDefined( USHORT nVer )
		{ nNewStandardDefined = nVer; eType |= NUMBERFORMAT_DEFINED; }

	USHORT GetNewStandardDefined() const		{ return nNewStandardDefined; }
	BOOL IsAdditionalStandardDefined() const
		{ return nNewStandardDefined == SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS; }

	LanguageType GetLanguage() const            { return eLnge;}

	const String& GetFormatstring()	const	{ return sFormatstring; }

	// Build a format string of application defined keywords
	String GetMappedFormatstring( const NfKeywordTable& rKeywords,
									const LocaleDataWrapper& rLoc,
									BOOL bDontQuote = FALSE ) const;

	void SetUsed(const BOOL b)					{ bIsUsed = b; }
	BOOL GetUsed() const						{ return bIsUsed; }
	BOOL IsStarFormatSupported() const			{ return bStarFlag; }
	void SetStarFormatSupport( BOOL b )			{ bStarFlag = b; }

	NfHackConversion Load( SvStream& rStream, ImpSvNumMultipleReadHeader& rHdr,
		SvNumberFormatter* pConverter, ImpSvNumberInputScan& rISc );
	void Save( SvStream& rStream, ImpSvNumMultipleWriteHeader& rHdr  ) const;

	// Load a string which might contain an Euro symbol,
	// in fact that could be any string used in number formats.
	static void LoadString( SvStream& rStream, String& rStr );

	BOOL GetOutputString( double fNumber, String& OutString, Color** ppColor );
	BOOL GetOutputString( String& sString, String& OutString, Color** ppColor );

	// True if type text
	BOOL IsTextFormat() const { return (eType & NUMBERFORMAT_TEXT) != 0; }
	// True if 4th subformat present
	BOOL HasTextFormat() const
		{
			return (NumFor[3].GetnAnz() > 0) ||
				(NumFor[3].Info().eScannedType == NUMBERFORMAT_TEXT);
		}

	void GetFormatSpecialInfo(BOOL& bThousand,
							  BOOL& IsRed,
							  USHORT& nPrecision,
							  USHORT& nAnzLeading) const;

	/// Count of decimal precision
	USHORT GetFormatPrecision() const	{ return NumFor[0].Info().nCntPost; }

	//! Read/write access on a special USHORT component, may only be used on the
	//! standard format 0, 5000, ... and only by the number formatter!
	USHORT GetLastInsertKey() const
		{ return NumFor[0].Info().nThousand; }
	void SetLastInsertKey(USHORT nKey)
		{ NumFor[0].Info().nThousand = nKey; }

	//! Only onLoad: convert from stored to current system language/country
	void ConvertLanguage( SvNumberFormatter& rConverter,
		LanguageType eConvertFrom, LanguageType eConvertTo, BOOL bSystem = FALSE );

	// Substring of a subformat code nNumFor (0..3)
	// nPos == 0xFFFF => last substring
	// bString==TRUE: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
	const String* GetNumForString( USHORT nNumFor, USHORT nPos,
			BOOL bString = FALSE ) const;

	// Subtype of a subformat code nNumFor (0..3)
	// nPos == 0xFFFF => last substring
	// bString==TRUE: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
	short GetNumForType( USHORT nNumFor, USHORT nPos, BOOL bString = FALSE ) const;

	// Whether the second subformat code is really for negative numbers
	// or another limit set.
	BOOL IsNegativeRealNegative() const
		{
			return fLimit1 == 0.0 && fLimit2 == 0.0 &&
			( (eOp1 == NUMBERFORMAT_OP_GE && eOp2 == NUMBERFORMAT_OP_NO) ||
			  (eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT) ||
			  (eOp1 == NUMBERFORMAT_OP_NO && eOp2 == NUMBERFORMAT_OP_NO) );
		}

	// Whether the negative format is without a sign or not
	BOOL IsNegativeWithoutSign() const;

	// Whether a new SYMBOLTYPE_CURRENCY is contained in the format
	BOOL HasNewCurrency() const;

	// Build string from NewCurrency for saving it SO50 compatible
	void Build50Formatstring( String& rStr ) const;

	// strip [$-yyy] from all [$xxx-yyy] leaving only xxx's,
	// if bQuoteSymbol==TRUE the xxx will become "xxx"
	static String StripNewCurrencyDelimiters( const String& rStr,
		BOOL bQuoteSymbol );

	// If a new SYMBOLTYPE_CURRENCY is contained if the format is of type
	// NUMBERFORMAT_CURRENCY, and if so the symbol xxx and the extension nnn
	// of [$xxx-nnn] are returned
	BOOL GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const;

	static BOOL HasStringNegativeSign( const String& rStr );

	/**
		Whether a character at position nPos is somewhere between two matching
		cQuote or not.
		If nPos points to a cQuote, a TRUE is returned on an opening cQuote,
		a FALSE is returned on a closing cQuote.
		A cQuote between quotes may be escaped by a cEscIn, a cQuote outside of
		quotes may be escaped by a cEscOut.
		The default '\0' results in no escapement possible.
		Defaults are set right according to the "unlogic" of the Numberformatter
	 */
	static BOOL IsInQuote( const String& rString, xub_StrLen nPos,
			sal_Unicode cQuote = '"',
			sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' );

	/**
		Return the position of a matching closing cQuote if the character at
		position nPos is between two matching cQuote, otherwise return
		STRING_NOTFOUND.
		If nPos points to an opening cQuote the position of the matching
	 	closing cQuote is returned.
		If nPos points to a closing cQuote nPos is returned.
		If nPos points into a part which starts with an opening cQuote but has
		no closing cQuote, rString.Len() is returned.
		Uses <method>IsInQuote</method> internally, so you don't have to call
		that prior to a call of this method.
	 */
	static xub_StrLen GetQuoteEnd( const String& rString, xub_StrLen nPos,
				sal_Unicode cQuote = '"',
				sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' );

	void SetComment( const String& rStr )
#if NF_COMMENT_IN_FORMATSTRING
		{ SetComment( rStr, sFormatstring, sComment ); }
#else
		{ sComment = rStr; }
#endif
	const String& GetComment() const { return sComment; }

	// Erase "{ "..." }" from format subcode string to get the pure comment (old version)
	static void EraseCommentBraces( String& rStr );
	// Set comment rStr in format string rFormat and in rComment (old version)
	static void SetComment( const String& rStr, String& rFormat, String& rComment );
	// Erase comment at end of rStr to get pure format code string (old version)
	static void EraseComment( String& rStr );

    /** Insert the number of blanks into the string that is needed to simulate
        the width of character c for underscore formats */
    static xub_StrLen InsertBlanks( String& r, xub_StrLen nPos, sal_Unicode c );

	DateFormat GetDateOrder() const;	// YMD,DMY,MDY if date format

	ImpSvNumberformatScan& ImpGetScan() const { return rScan; }

	// used in XML export
	void GetConditions( SvNumberformatLimitOps& rOper1, double& rVal1,
						SvNumberformatLimitOps& rOper2, double& rVal2 ) const;
	Color* GetColor( USHORT nNumFor ) const;
	void GetNumForInfo( USHORT nNumFor, short& rScannedType,
					BOOL& bThousand, USHORT& nPrecision, USHORT& nAnzLeading ) const;

	BYTE GetDBNumNum( USHORT nNumFor ) const
		{ return nNumFor <= 3 ? NumFor[nNumFor].GetDBNum().nNum : 0; }
	LanguageType GetDBNumLang( USHORT nNumFor ) const
		{ return nNumFor <= 3 ? NumFor[nNumFor].GetDBNum().eLang : LANGUAGE_DONTKNOW; }

private:
	static ::rtl::OUString sGregorian;	// The string "gregorian"

	ImpSvNumFor NumFor[4];			// Array for the 4 subformats
	String sFormatstring;			// The format code string
	String sComment;				// Comment, since number formatter version 6
	double fLimit1;					// Value for first condition
	double fLimit2;					// Value for second condition
	ImpSvNumberformatScan& rScan;	// Format code scanner
	LanguageType eLnge;				// Language/country of the format
	SvNumberformatLimitOps eOp1;	// Operator for first condition
	SvNumberformatLimitOps eOp2;	// Operator for second condition
	USHORT nNewStandardDefined;		// new builtin formats as of version 6
	short eType;					// Type of format
	BOOL bStarFlag;					// Take *n format as ESC n
	BOOL bStandard;					// If this is a default standard format
	BOOL bIsUsed;					// Flag as used for storing

#ifdef _ZFORMAT_CXX		// ----- private implementation methods -----

	const CharClass& rChrCls() const		{ return rScan.GetChrCls(); }
	const LocaleDataWrapper& rLoc() const	{ return rScan.GetLoc(); }
	CalendarWrapper& GetCal() const			{ return rScan.GetCal(); }
    const SvNumberFormatter& GetFormatter() const   { return *rScan.GetNumberformatter(); }

	// divide in substrings and color conditions
	short ImpNextSymbol( String& rString,
					 xub_StrLen& nPos,
					 String& sSymbol );

	// read string until ']' and strip blanks (after condition)
	static xub_StrLen ImpGetNumber( String& rString,
				   xub_StrLen& nPos,
				   String& sSymbol );

	// get xxx of "[$-xxx]" as LanguageType, starting at and advancing position nPos
	static LanguageType ImpGetLanguageType( const String& rString, xub_StrLen& nPos );

	// standard number output
	void ImpGetOutputStandard( double& fNumber, String& OutString );
	// numbers in input line
	void ImpGetOutputInputLine( double fNumber, String& OutString );

	// check subcondition
	// OP undefined => -1
	// else 0 or 1
	short ImpCheckCondition(double& fNumber,
						 double& fLimit,
						 SvNumberformatLimitOps eOp);

	ULONG ImpGGT(ULONG x, ULONG y);
	ULONG ImpGGTRound(ULONG x, ULONG y);

	// Helper function for number strings
	// append string symbols, insert leading 0 or ' ', or ...
	BOOL ImpNumberFill( String& sStr,
					double& rNumber,
					xub_StrLen& k,
					USHORT& j,
					USHORT nIx,
					short eSymbolType );

	// Helper function to fill in the integer part and the group (AKA thousand) separators
	BOOL ImpNumberFillWithThousands( String& sStr,
								 double& rNumber,
								 xub_StrLen k,
								 USHORT j,
								 USHORT nIx,
								 USHORT nDigCnt );
									// Hilfsfunktion zum Auffuellen der Vor-
									// kommazahl auch mit Tausenderpunkt

	// Helper function to fill in the group (AKA thousand) separators
	// or to skip additional digits
	void ImpDigitFill( String& sStr,
					xub_StrLen nStart,
					xub_StrLen& k,
					USHORT nIx,
					USHORT nThousandCnt );

	BOOL ImpGetDateOutput( double fNumber,
					   USHORT nIx,
					   String& OutString );
	BOOL ImpGetTimeOutput( double fNumber,
					   USHORT nIx,
					   String& OutString );
	BOOL ImpGetDateTimeOutput( double fNumber,
						   USHORT nIx,
						   String& OutString );

	// TRUE if E,EE,R,RR,AAA,AAAA in format code and _no_ preceding calendar
	// specified and the currently loaded calendar is "gregorian"
	BOOL IsOtherCalendar( const ImpSvNumFor& rNumFor ) const;

	// Switches to the first non-"gregorian" calendar, but only if the current
	// calendar is "gregorian"; original calendar name and date/time returned,
	// but only if calendar switched and rOrgCalendar was empty.
	void SwitchToOtherCalendar( String& rOrgCalendar, double& fOrgDateTime );

	// Switches to the "gregorian" calendar, but only if the current calendar
	// is non-"gregorian" and rOrgCalendar is not empty. Thus a preceding
	// SwitchToOtherCalendar() call should have been placed prior to calling
	// this method.
	void SwitchToGregorianCalendar( const String& rOrgCalendar, double fOrgDateTime );

    // Switches to the "gregorian" calendar if the current calendar is
    // non-"gregorian" and the era is a "Dummy" era of a calendar which doesn't
    // know a "before" era (like zh_TW ROC or ja_JP Gengou). If switched and
    // rOrgCalendar was "gregorian" the string is emptied. If rOrgCalendar was
    // empty the previous calendar name and date/time are returned.
    BOOL FallBackToGregorianCalendar( String& rOrgCalendar, double& fOrgDateTime );

	BOOL ImpGetNumberOutput( double fNumber,
						 USHORT nIx,
						 String& OutString );

	void CopyNumberformat( const SvNumberformat& rFormat );

	// normal digits or other digits, depending on ImpSvNumFor.aDBNum,
	// [DBNum1] ... [DBNum9]
	String GetDBNumString( const SvNumberDBNum& rNum, sal_Int32 nVal, USHORT nMinDigits = 0  ) const;
	String IntToString( USHORT nIx, sal_Int32 nVal, USHORT nMinDigits = 0 ) const
		{
			const SvNumberDBNum& rNum = NumFor[nIx].GetDBNum();
			if ( nMinDigits || rNum.IsComplete() )
				return GetDBNumString( rNum, nVal, nMinDigits );
			return String::CreateFromInt32( nVal );
		}

#endif // _ZFORMAT_CXX
};

#endif	// _ZFORMAT_HXX
