xref: /aoo41x/main/svl/inc/svl/zformat.hxx (revision 5ff14ef2)
139a19a47SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
339a19a47SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
439a19a47SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
539a19a47SAndrew Rist  * distributed with this work for additional information
639a19a47SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
739a19a47SAndrew Rist  * to you under the Apache License, Version 2.0 (the
839a19a47SAndrew Rist  * "License"); you may not use this file except in compliance
939a19a47SAndrew Rist  * with the License.  You may obtain a copy of the License at
1039a19a47SAndrew Rist  *
1139a19a47SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
1239a19a47SAndrew Rist  *
1339a19a47SAndrew Rist  * Unless required by applicable law or agreed to in writing,
1439a19a47SAndrew Rist  * software distributed under the License is distributed on an
1539a19a47SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
1639a19a47SAndrew Rist  * KIND, either express or implied.  See the License for the
1739a19a47SAndrew Rist  * specific language governing permissions and limitations
1839a19a47SAndrew Rist  * under the License.
1939a19a47SAndrew Rist  *
2039a19a47SAndrew Rist  *************************************************************/
2139a19a47SAndrew Rist 
2239a19a47SAndrew Rist 
23cdf0e10cSrcweir #ifndef _ZFORMAT_HXX
24cdf0e10cSrcweir #define _ZFORMAT_HXX
25cdf0e10cSrcweir 
26cdf0e10cSrcweir #include "svl/svldllapi.h"
27cdf0e10cSrcweir #include <tools/string.hxx>
28cdf0e10cSrcweir #include <i18npool/mslangid.hxx>
29cdf0e10cSrcweir #include <svl/zforlist.hxx>
30cdf0e10cSrcweir #include <svl/nfversi.hxx>
31cdf0e10cSrcweir #include <svl/nfkeytab.hxx>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir // We need ImpSvNumberformatScan for the private SvNumberformat definitions.
34cdf0e10cSrcweir #ifdef _ZFORMAT_CXX
35cdf0e10cSrcweir #include "zforscan.hxx"
36cdf0e10cSrcweir #endif
37cdf0e10cSrcweir 
38cdf0e10cSrcweir // If comment field is also in format code string, was used for SUPD versions 371-372
39cdf0e10cSrcweir #define NF_COMMENT_IN_FORMATSTRING 0
40cdf0e10cSrcweir 
41cdf0e10cSrcweir namespace utl {
42cdf0e10cSrcweir     class DigitGroupingIterator;
43cdf0e10cSrcweir }
44cdf0e10cSrcweir 
45cdf0e10cSrcweir class SvStream;
46cdf0e10cSrcweir class Color;
47cdf0e10cSrcweir 
48cdf0e10cSrcweir class ImpSvNumberformatScan;            // format code string scanner
49cdf0e10cSrcweir class ImpSvNumberInputScan;             // input string scanner
50cdf0e10cSrcweir class ImpSvNumMultipleWriteHeader;      // compatible file format
51cdf0e10cSrcweir class ImpSvNumMultipleReadHeader;       // compatible file format
52cdf0e10cSrcweir class SvNumberFormatter;
53cdf0e10cSrcweir 
54cdf0e10cSrcweir enum SvNumberformatLimitOps
55cdf0e10cSrcweir {
56cdf0e10cSrcweir     NUMBERFORMAT_OP_NO  = 0,            // Undefined, no OP
57cdf0e10cSrcweir     NUMBERFORMAT_OP_EQ  = 1,            // Operator =
58cdf0e10cSrcweir     NUMBERFORMAT_OP_NE  = 2,            // Operator <>
59cdf0e10cSrcweir     NUMBERFORMAT_OP_LT  = 3,            // Operator <
60cdf0e10cSrcweir     NUMBERFORMAT_OP_LE  = 4,            // Operator <=
61cdf0e10cSrcweir     NUMBERFORMAT_OP_GT  = 5,            // Operator >
62cdf0e10cSrcweir     NUMBERFORMAT_OP_GE  = 6             // Operator >=
63cdf0e10cSrcweir };
64cdf0e10cSrcweir 
65cdf0e10cSrcweir // SYSTEM-german to SYSTEM-xxx and vice versa conversion hack onLoad
66cdf0e10cSrcweir enum NfHackConversion
67cdf0e10cSrcweir {
68cdf0e10cSrcweir     NF_CONVERT_NONE,
69cdf0e10cSrcweir     NF_CONVERT_GERMAN_ENGLISH,
70cdf0e10cSrcweir     NF_CONVERT_ENGLISH_GERMAN
71cdf0e10cSrcweir };
72cdf0e10cSrcweir 
73cdf0e10cSrcweir struct ImpSvNumberformatInfo            // Struct for FormatInfo
74cdf0e10cSrcweir {
75cdf0e10cSrcweir     String* sStrArray;                  // Array of symbols
76cdf0e10cSrcweir     short* nTypeArray;                  // Array of infos
77cdf0e10cSrcweir     sal_uInt16 nThousand;                   // Count of group separator sequences
78cdf0e10cSrcweir     sal_uInt16 nCntPre;                     // Count of digits before decimal point
79cdf0e10cSrcweir     sal_uInt16 nCntPost;                    // Count of digits after decimal point
80cdf0e10cSrcweir     sal_uInt16 nCntExp;                     // Count of exponent digits, or AM/PM
81cdf0e10cSrcweir     short eScannedType;                 // Type determined by scan
82cdf0e10cSrcweir     sal_Bool bThousand;                     // Has group (AKA thousand) separator
83cdf0e10cSrcweir 
84cdf0e10cSrcweir     void Copy( const ImpSvNumberformatInfo& rNumFor, sal_uInt16 nAnz );
85cdf0e10cSrcweir     void Load(SvStream& rStream, sal_uInt16 nAnz);
86cdf0e10cSrcweir     void Save(SvStream& rStream, sal_uInt16 nAnz) const;
87cdf0e10cSrcweir };
88cdf0e10cSrcweir 
89cdf0e10cSrcweir // NativeNumber, represent numbers using CJK or other digits if nNum>0,
90cdf0e10cSrcweir // eLang specifies the Locale to use.
91cdf0e10cSrcweir class SvNumberNatNum
92cdf0e10cSrcweir {
93cdf0e10cSrcweir     LanguageType    eLang;
94cdf0e10cSrcweir     sal_uInt8            nNum;
95cdf0e10cSrcweir     sal_Bool            bDBNum  :1;     // DBNum, to be converted to NatNum
96cdf0e10cSrcweir     sal_Bool            bDate   :1;     // Used in date? (needed for DBNum/NatNum mapping)
97cdf0e10cSrcweir     sal_Bool            bSet    :1;     // If set, since NatNum0 is possible
98cdf0e10cSrcweir 
99cdf0e10cSrcweir public:
100cdf0e10cSrcweir 
101cdf0e10cSrcweir     static  sal_uInt8    MapDBNumToNatNum( sal_uInt8 nDBNum, LanguageType eLang, sal_Bool bDate );
102cdf0e10cSrcweir     static  sal_uInt8    MapNatNumToDBNum( sal_uInt8 nNatNum, LanguageType eLang, sal_Bool bDate );
103cdf0e10cSrcweir 
SvNumberNatNum()104cdf0e10cSrcweir                     SvNumberNatNum() : eLang( LANGUAGE_DONTKNOW ), nNum(0),
105cdf0e10cSrcweir                                         bDBNum(0), bDate(0), bSet(0) {}
IsComplete() const106cdf0e10cSrcweir     sal_Bool            IsComplete() const  { return bSet && eLang != LANGUAGE_DONTKNOW; }
GetRawNum() const107cdf0e10cSrcweir     sal_uInt8            GetRawNum() const   { return nNum; }
GetNatNum() const108cdf0e10cSrcweir     sal_uInt8            GetNatNum() const   { return bDBNum ? MapDBNumToNatNum( nNum, eLang, bDate ) : nNum; }
GetDBNum() const109cdf0e10cSrcweir     sal_uInt8            GetDBNum() const    { return bDBNum ? nNum : MapNatNumToDBNum( nNum, eLang, bDate ); }
GetLang() const110cdf0e10cSrcweir     LanguageType    GetLang() const     { return eLang; }
SetLang(LanguageType e)111cdf0e10cSrcweir     void            SetLang( LanguageType e ) { eLang = e; }
SetNum(sal_uInt8 nNumber,sal_Bool bDBNumber)112cdf0e10cSrcweir     void            SetNum( sal_uInt8 nNumber, sal_Bool bDBNumber )
113cdf0e10cSrcweir                         {
114cdf0e10cSrcweir                             nNum = nNumber;
115cdf0e10cSrcweir                             bDBNum = bDBNumber;
116cdf0e10cSrcweir                             bSet = sal_True;
117cdf0e10cSrcweir                         }
IsSet() const118cdf0e10cSrcweir     sal_Bool            IsSet() const       { return bSet; }
SetDate(sal_Bool bDateP)119cdf0e10cSrcweir     void            SetDate( sal_Bool bDateP )   { bDate = (bDateP != 0); }
120cdf0e10cSrcweir };
121cdf0e10cSrcweir 
122cdf0e10cSrcweir class CharClass;
123cdf0e10cSrcweir 
124cdf0e10cSrcweir class ImpSvNumFor                       // One of four subformats of the format code string
125cdf0e10cSrcweir {
126cdf0e10cSrcweir public:
127cdf0e10cSrcweir     ImpSvNumFor();                      // Ctor without filling the Info
128cdf0e10cSrcweir     ~ImpSvNumFor();
129cdf0e10cSrcweir 
130cdf0e10cSrcweir     void Enlarge(sal_uInt16 nAnz);          // Init of arrays to the right size
131cdf0e10cSrcweir     void Load( SvStream& rStream, ImpSvNumberformatScan& rSc,
132cdf0e10cSrcweir                 String& rLoadedColorName);
133cdf0e10cSrcweir     void Save( SvStream& rStream ) const;
134cdf0e10cSrcweir 
135cdf0e10cSrcweir     // if pSc is set, it is used to get the Color pointer
136cdf0e10cSrcweir     void Copy( const ImpSvNumFor& rNumFor, ImpSvNumberformatScan* pSc );
137cdf0e10cSrcweir 
138cdf0e10cSrcweir     // Access to Info; call Enlarge before!
Info()139cdf0e10cSrcweir     ImpSvNumberformatInfo& Info() { return aI;}
Info() const140cdf0e10cSrcweir     const ImpSvNumberformatInfo& Info() const { return aI; }
141cdf0e10cSrcweir 
142cdf0e10cSrcweir     // Get count of substrings (symbols)
GetnAnz() const143cdf0e10cSrcweir     sal_uInt16 GetnAnz() const { return nAnzStrings;}
144cdf0e10cSrcweir 
GetColor() const145cdf0e10cSrcweir     Color* GetColor() const { return pColor; }
SetColor(Color * pCol,String & rName)146cdf0e10cSrcweir     void SetColor( Color* pCol, String& rName )
147cdf0e10cSrcweir      { pColor = pCol; sColorName = rName; }
GetColorName() const148cdf0e10cSrcweir     const String& GetColorName() const { return sColorName; }
149cdf0e10cSrcweir 
150cdf0e10cSrcweir     // new SYMBOLTYPE_CURRENCY in subformat?
151cdf0e10cSrcweir     sal_Bool HasNewCurrency() const;
152cdf0e10cSrcweir     sal_Bool GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const;
153cdf0e10cSrcweir     void SaveNewCurrencyMap( SvStream& rStream ) const;
154cdf0e10cSrcweir     void LoadNewCurrencyMap( SvStream& rStream );
155cdf0e10cSrcweir 
156cdf0e10cSrcweir     // [NatNum1], [NatNum2], ...
SetNatNumNum(sal_uInt8 nNum,sal_Bool bDBNum)157cdf0e10cSrcweir     void SetNatNumNum( sal_uInt8 nNum, sal_Bool bDBNum ) { aNatNum.SetNum( nNum, bDBNum ); }
SetNatNumLang(LanguageType eLang)158cdf0e10cSrcweir     void SetNatNumLang( LanguageType eLang ) { aNatNum.SetLang( eLang ); }
SetNatNumDate(sal_Bool bDate)159cdf0e10cSrcweir     void SetNatNumDate( sal_Bool bDate ) { aNatNum.SetDate( bDate ); }
GetNatNum() const160cdf0e10cSrcweir     const SvNumberNatNum& GetNatNum() const { return aNatNum; }
161cdf0e10cSrcweir 
162fe481f06SOliver-Rainer Wittmann     // check, if the format code contains a subformat for text
163*5ff14ef2SHerbert Dürr     bool HasTextFormatCode() const;
164fe481f06SOliver-Rainer Wittmann 
165cdf0e10cSrcweir private:
166cdf0e10cSrcweir     ImpSvNumberformatInfo aI;           // Hilfsstruct fuer die restlichen Infos
167cdf0e10cSrcweir     String sColorName;                  // color name
168cdf0e10cSrcweir     Color* pColor;                      // pointer to color of subformat
169cdf0e10cSrcweir     sal_uInt16 nAnzStrings;                 // count of symbols
170cdf0e10cSrcweir     SvNumberNatNum aNatNum;             // DoubleByteNumber
171cdf0e10cSrcweir 
172cdf0e10cSrcweir };
173cdf0e10cSrcweir 
174cdf0e10cSrcweir class SVL_DLLPUBLIC SvNumberformat
175cdf0e10cSrcweir {
176cdf0e10cSrcweir public:
177cdf0e10cSrcweir     // Ctor for Load
178cdf0e10cSrcweir     SvNumberformat( ImpSvNumberformatScan& rSc, LanguageType eLge );
179cdf0e10cSrcweir 
180cdf0e10cSrcweir     // Normal ctor
181cdf0e10cSrcweir     SvNumberformat( String& rString,
182cdf0e10cSrcweir                    ImpSvNumberformatScan* pSc,
183cdf0e10cSrcweir                    ImpSvNumberInputScan* pISc,
184cdf0e10cSrcweir                    xub_StrLen& nCheckPos,
185cdf0e10cSrcweir                    LanguageType& eLan,
186cdf0e10cSrcweir                    sal_Bool bStand = sal_False );
187cdf0e10cSrcweir 
188cdf0e10cSrcweir     // Copy ctor
189cdf0e10cSrcweir     SvNumberformat( SvNumberformat& rFormat );
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     // Copy ctor with exchange of format code string scanner (used in merge)
192cdf0e10cSrcweir     SvNumberformat( SvNumberformat& rFormat, ImpSvNumberformatScan& rSc );
193cdf0e10cSrcweir 
194cdf0e10cSrcweir     ~SvNumberformat();
195cdf0e10cSrcweir 
196cdf0e10cSrcweir     /// Get type of format, may include NUMBERFORMAT_DEFINED bit
GetType() const197cdf0e10cSrcweir     short GetType() const
198cdf0e10cSrcweir         { return (nNewStandardDefined &&
199cdf0e10cSrcweir             (nNewStandardDefined <= SV_NUMBERFORMATTER_VERSION)) ?
200cdf0e10cSrcweir             (eType & ~NUMBERFORMAT_DEFINED) : eType; }
201cdf0e10cSrcweir 
SetType(const short eSetType)202cdf0e10cSrcweir     void SetType(const short eSetType)          { eType = eSetType; }
203cdf0e10cSrcweir     // Standard means the I18N defined standard format of this type
SetStandard()204cdf0e10cSrcweir     void SetStandard()                          { bStandard = sal_True; }
IsStandard() const205cdf0e10cSrcweir     sal_Bool IsStandard() const                     { return bStandard; }
206cdf0e10cSrcweir 
207cdf0e10cSrcweir     // For versions before version nVer it is UserDefined, for newer versions
208cdf0e10cSrcweir     // it is builtin. nVer of SV_NUMBERFORMATTER_VERSION_...
SetNewStandardDefined(sal_uInt16 nVer)209cdf0e10cSrcweir     void SetNewStandardDefined( sal_uInt16 nVer )
210cdf0e10cSrcweir         { nNewStandardDefined = nVer; eType |= NUMBERFORMAT_DEFINED; }
211cdf0e10cSrcweir 
GetNewStandardDefined() const212cdf0e10cSrcweir     sal_uInt16 GetNewStandardDefined() const        { return nNewStandardDefined; }
IsAdditionalStandardDefined() const213cdf0e10cSrcweir     sal_Bool IsAdditionalStandardDefined() const
214cdf0e10cSrcweir         { return nNewStandardDefined == SV_NUMBERFORMATTER_VERSION_ADDITIONAL_I18N_FORMATS; }
215cdf0e10cSrcweir 
GetLanguage() const216cdf0e10cSrcweir     LanguageType GetLanguage() const            { return eLnge;}
217cdf0e10cSrcweir 
GetFormatstring() const218cdf0e10cSrcweir     const String& GetFormatstring() const   { return sFormatstring; }
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     // Build a format string of application defined keywords
221cdf0e10cSrcweir     String GetMappedFormatstring( const NfKeywordTable& rKeywords,
222cdf0e10cSrcweir                                     const LocaleDataWrapper& rLoc,
223cdf0e10cSrcweir                                     sal_Bool bDontQuote = sal_False ) const;
224cdf0e10cSrcweir 
SetUsed(const sal_Bool b)225cdf0e10cSrcweir     void SetUsed(const sal_Bool b)                  { bIsUsed = b; }
GetUsed() const226cdf0e10cSrcweir     sal_Bool GetUsed() const                        { return bIsUsed; }
IsStarFormatSupported() const227cdf0e10cSrcweir     sal_Bool IsStarFormatSupported() const          { return bStarFlag; }
SetStarFormatSupport(sal_Bool b)228cdf0e10cSrcweir     void SetStarFormatSupport( sal_Bool b )         { bStarFlag = b; }
229cdf0e10cSrcweir 
230cdf0e10cSrcweir     NfHackConversion Load( SvStream& rStream, ImpSvNumMultipleReadHeader& rHdr,
231cdf0e10cSrcweir         SvNumberFormatter* pConverter, ImpSvNumberInputScan& rISc );
232cdf0e10cSrcweir     void Save( SvStream& rStream, ImpSvNumMultipleWriteHeader& rHdr  ) const;
233cdf0e10cSrcweir 
234cdf0e10cSrcweir     // Load a string which might contain an Euro symbol,
235cdf0e10cSrcweir     // in fact that could be any string used in number formats.
236cdf0e10cSrcweir     static void LoadString( SvStream& rStream, String& rStr );
237cdf0e10cSrcweir 
238cdf0e10cSrcweir     /**
239cdf0e10cSrcweir      * Get output string from a numeric value that fits the number of
240cdf0e10cSrcweir      * characters specified.
241cdf0e10cSrcweir      */
242cdf0e10cSrcweir     bool GetOutputString( double fNumber, sal_uInt16 nCharCount, String& rOutString ) const;
243cdf0e10cSrcweir 
244cdf0e10cSrcweir     sal_Bool GetOutputString( double fNumber, String& OutString, Color** ppColor );
245cdf0e10cSrcweir     sal_Bool GetOutputString( String& sString, String& OutString, Color** ppColor );
246cdf0e10cSrcweir 
247cdf0e10cSrcweir     // True if type text
IsTextFormat() const248cdf0e10cSrcweir     sal_Bool IsTextFormat() const { return (eType & NUMBERFORMAT_TEXT) != 0; }
249cdf0e10cSrcweir     // True if 4th subformat present
HasTextFormat() const250cdf0e10cSrcweir     sal_Bool HasTextFormat() const
251cdf0e10cSrcweir         {
252cdf0e10cSrcweir             return (NumFor[3].GetnAnz() > 0) ||
253cdf0e10cSrcweir                 (NumFor[3].Info().eScannedType == NUMBERFORMAT_TEXT);
254cdf0e10cSrcweir         }
255cdf0e10cSrcweir 
256cdf0e10cSrcweir     void GetFormatSpecialInfo(sal_Bool& bThousand,
257cdf0e10cSrcweir                               sal_Bool& IsRed,
258cdf0e10cSrcweir                               sal_uInt16& nPrecision,
259cdf0e10cSrcweir                               sal_uInt16& nAnzLeading) const;
260cdf0e10cSrcweir 
261cdf0e10cSrcweir     /// Count of decimal precision
GetFormatPrecision() const262cdf0e10cSrcweir     sal_uInt16 GetFormatPrecision() const   { return NumFor[0].Info().nCntPost; }
263cdf0e10cSrcweir 
264cdf0e10cSrcweir     //! Read/write access on a special sal_uInt16 component, may only be used on the
265cdf0e10cSrcweir     //! standard format 0, 5000, ... and only by the number formatter!
GetLastInsertKey() const266cdf0e10cSrcweir     sal_uInt16 GetLastInsertKey() const
267cdf0e10cSrcweir         { return NumFor[0].Info().nThousand; }
SetLastInsertKey(sal_uInt16 nKey)268cdf0e10cSrcweir     void SetLastInsertKey(sal_uInt16 nKey)
269cdf0e10cSrcweir         { NumFor[0].Info().nThousand = nKey; }
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     //! Only onLoad: convert from stored to current system language/country
272cdf0e10cSrcweir     void ConvertLanguage( SvNumberFormatter& rConverter,
273cdf0e10cSrcweir         LanguageType eConvertFrom, LanguageType eConvertTo, sal_Bool bSystem = sal_False );
274cdf0e10cSrcweir 
275cdf0e10cSrcweir     // Substring of a subformat code nNumFor (0..3)
276cdf0e10cSrcweir     // nPos == 0xFFFF => last substring
277cdf0e10cSrcweir     // bString==sal_True: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
278cdf0e10cSrcweir     const String* GetNumForString( sal_uInt16 nNumFor, sal_uInt16 nPos,
279cdf0e10cSrcweir             sal_Bool bString = sal_False ) const;
280cdf0e10cSrcweir 
281cdf0e10cSrcweir     // Subtype of a subformat code nNumFor (0..3)
282cdf0e10cSrcweir     // nPos == 0xFFFF => last substring
283cdf0e10cSrcweir     // bString==sal_True: first/last SYMBOLTYPE_STRING or SYMBOLTYPE_CURRENCY
284cdf0e10cSrcweir     short GetNumForType( sal_uInt16 nNumFor, sal_uInt16 nPos, sal_Bool bString = sal_False ) const;
285cdf0e10cSrcweir 
286cdf0e10cSrcweir     /** If the count of string elements (substrings, ignoring [modifiers] and
287cdf0e10cSrcweir         so on) in a subformat code nNumFor (0..3) is equal to the given number.
288cdf0e10cSrcweir         Used by ImpSvNumberInputScan::IsNumberFormatMain() to detect a matched
289cdf0e10cSrcweir         format.  */
IsNumForStringElementCountEqual(sal_uInt16 nNumFor,sal_uInt16 nAllCount,sal_uInt16 nNumCount) const290cdf0e10cSrcweir     sal_Bool IsNumForStringElementCountEqual( sal_uInt16 nNumFor, sal_uInt16 nAllCount,
291cdf0e10cSrcweir             sal_uInt16 nNumCount ) const
292cdf0e10cSrcweir         {
293cdf0e10cSrcweir             if ( nNumFor < 4 )
294cdf0e10cSrcweir             {
295cdf0e10cSrcweir                 // First try a simple approach. Note that this is called only
296cdf0e10cSrcweir                 // if all MidStrings did match so far, to verify that all
297cdf0e10cSrcweir                 // strings of the format were matched and not just the starting
298cdf0e10cSrcweir                 // sequence, so we don't have to check if GetnAnz() includes
299cdf0e10cSrcweir                 // [modifiers] or anything else if both counts are equal.
300cdf0e10cSrcweir                 sal_uInt16 nCnt = NumFor[nNumFor].GetnAnz();
301cdf0e10cSrcweir                 if ( nAllCount == nCnt )
302cdf0e10cSrcweir                     return sal_True;
303cdf0e10cSrcweir                 if ( nAllCount < nCnt ) // check ignoring [modifiers] and so on
304cdf0e10cSrcweir                     return ImpGetNumForStringElementCount( nNumFor ) ==
305cdf0e10cSrcweir                         (nAllCount - nNumCount);
306cdf0e10cSrcweir             }
307cdf0e10cSrcweir             return sal_False;
308cdf0e10cSrcweir         }
309cdf0e10cSrcweir 
310cdf0e10cSrcweir     // Whether the second subformat code is really for negative numbers
311cdf0e10cSrcweir     // or another limit set.
IsNegativeRealNegative() const312cdf0e10cSrcweir     sal_Bool IsNegativeRealNegative() const
313cdf0e10cSrcweir         {
314cdf0e10cSrcweir             return fLimit1 == 0.0 && fLimit2 == 0.0 &&
315cdf0e10cSrcweir             ( (eOp1 == NUMBERFORMAT_OP_GE && eOp2 == NUMBERFORMAT_OP_NO) ||
316cdf0e10cSrcweir               (eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT) ||
317cdf0e10cSrcweir               (eOp1 == NUMBERFORMAT_OP_NO && eOp2 == NUMBERFORMAT_OP_NO) );
318cdf0e10cSrcweir         }
319f85760deSWang Lei 	// Whether the first subformat code is really for negative numbers
320f85760deSWang Lei     // or another limit set.
IsNegativeRealNegative2() const321f85760deSWang Lei     sal_Bool IsNegativeRealNegative2() const
322f85760deSWang Lei         {
323f85760deSWang Lei             return fLimit1 == 0.0 && fLimit2 == 0.0 &&
324f85760deSWang Lei             ( (eOp2 == NUMBERFORMAT_OP_GT && eOp1 == NUMBERFORMAT_OP_LT) ||
325f85760deSWang Lei 			  (eOp2 == NUMBERFORMAT_OP_EQ && eOp1 == NUMBERFORMAT_OP_LT) ||
326f85760deSWang Lei 			  (eOp2 == NUMBERFORMAT_OP_GE && eOp1 == NUMBERFORMAT_OP_LT) ||
327f85760deSWang Lei 			  (eOp2 == NUMBERFORMAT_OP_NO && eOp1 == NUMBERFORMAT_OP_LT) ||
328f85760deSWang Lei 			  (eOp2 == NUMBERFORMAT_OP_NO && eOp1 == NUMBERFORMAT_OP_LE) ||
329f85760deSWang Lei 			  (eOp2 == NUMBERFORMAT_OP_GT && eOp1 == NUMBERFORMAT_OP_LE));
330f85760deSWang Lei         }
331cdf0e10cSrcweir 
332cdf0e10cSrcweir     // Whether the negative format is without a sign or not
333cdf0e10cSrcweir     sal_Bool IsNegativeWithoutSign() const;
334cdf0e10cSrcweir 
335cdf0e10cSrcweir     // Whether a new SYMBOLTYPE_CURRENCY is contained in the format
336cdf0e10cSrcweir     sal_Bool HasNewCurrency() const;
337cdf0e10cSrcweir 
338fe481f06SOliver-Rainer Wittmann     // check, if the format code contains a subformat for text
339*5ff14ef2SHerbert Dürr     bool HasTextFormatCode() const;
340fe481f06SOliver-Rainer Wittmann 
341cdf0e10cSrcweir     // Build string from NewCurrency for saving it SO50 compatible
342cdf0e10cSrcweir     void Build50Formatstring( String& rStr ) const;
343cdf0e10cSrcweir 
344cdf0e10cSrcweir     // strip [$-yyy] from all [$xxx-yyy] leaving only xxx's,
345cdf0e10cSrcweir     // if bQuoteSymbol==sal_True the xxx will become "xxx"
346cdf0e10cSrcweir     static String StripNewCurrencyDelimiters( const String& rStr,
347cdf0e10cSrcweir         sal_Bool bQuoteSymbol );
348cdf0e10cSrcweir 
349cdf0e10cSrcweir     // If a new SYMBOLTYPE_CURRENCY is contained if the format is of type
350cdf0e10cSrcweir     // NUMBERFORMAT_CURRENCY, and if so the symbol xxx and the extension nnn
351cdf0e10cSrcweir     // of [$xxx-nnn] are returned
352cdf0e10cSrcweir     sal_Bool GetNewCurrencySymbol( String& rSymbol, String& rExtension ) const;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir     static sal_Bool HasStringNegativeSign( const String& rStr );
355cdf0e10cSrcweir 
356cdf0e10cSrcweir     /**
357cdf0e10cSrcweir         Whether a character at position nPos is somewhere between two matching
358cdf0e10cSrcweir         cQuote or not.
359cdf0e10cSrcweir         If nPos points to a cQuote, a sal_True is returned on an opening cQuote,
360cdf0e10cSrcweir         a sal_False is returned on a closing cQuote.
361cdf0e10cSrcweir         A cQuote between quotes may be escaped by a cEscIn, a cQuote outside of
362cdf0e10cSrcweir         quotes may be escaped by a cEscOut.
363cdf0e10cSrcweir         The default '\0' results in no escapement possible.
364cdf0e10cSrcweir         Defaults are set right according to the "unlogic" of the Numberformatter
365cdf0e10cSrcweir      */
366cdf0e10cSrcweir     static sal_Bool IsInQuote( const String& rString, xub_StrLen nPos,
367cdf0e10cSrcweir             sal_Unicode cQuote = '"',
368cdf0e10cSrcweir             sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' );
369cdf0e10cSrcweir 
370cdf0e10cSrcweir     /**
371cdf0e10cSrcweir         Return the position of a matching closing cQuote if the character at
372cdf0e10cSrcweir         position nPos is between two matching cQuote, otherwise return
373cdf0e10cSrcweir         STRING_NOTFOUND.
374cdf0e10cSrcweir         If nPos points to an opening cQuote the position of the matching
375cdf0e10cSrcweir         closing cQuote is returned.
376cdf0e10cSrcweir         If nPos points to a closing cQuote nPos is returned.
377cdf0e10cSrcweir         If nPos points into a part which starts with an opening cQuote but has
378cdf0e10cSrcweir         no closing cQuote, rString.Len() is returned.
379cdf0e10cSrcweir         Uses <method>IsInQuote</method> internally, so you don't have to call
380cdf0e10cSrcweir         that prior to a call of this method.
381cdf0e10cSrcweir      */
382cdf0e10cSrcweir     static xub_StrLen GetQuoteEnd( const String& rString, xub_StrLen nPos,
383cdf0e10cSrcweir                 sal_Unicode cQuote = '"',
384cdf0e10cSrcweir                 sal_Unicode cEscIn = '\0', sal_Unicode cEscOut = '\\' );
385cdf0e10cSrcweir 
SetComment(const String & rStr)386cdf0e10cSrcweir     void SetComment( const String& rStr )
387cdf0e10cSrcweir #if NF_COMMENT_IN_FORMATSTRING
388cdf0e10cSrcweir         { SetComment( rStr, sFormatstring, sComment ); }
389cdf0e10cSrcweir #else
390cdf0e10cSrcweir         { sComment = rStr; }
391cdf0e10cSrcweir #endif
GetComment() const392cdf0e10cSrcweir     const String& GetComment() const { return sComment; }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir     // Erase "{ "..." }" from format subcode string to get the pure comment (old version)
395cdf0e10cSrcweir     static void EraseCommentBraces( String& rStr );
396cdf0e10cSrcweir     // Set comment rStr in format string rFormat and in rComment (old version)
397cdf0e10cSrcweir     static void SetComment( const String& rStr, String& rFormat, String& rComment );
398cdf0e10cSrcweir     // Erase comment at end of rStr to get pure format code string (old version)
399cdf0e10cSrcweir     static void EraseComment( String& rStr );
400cdf0e10cSrcweir 
401cdf0e10cSrcweir     /** Insert the number of blanks into the string that is needed to simulate
402cdf0e10cSrcweir         the width of character c for underscore formats */
403cdf0e10cSrcweir     static xub_StrLen InsertBlanks( String& r, xub_StrLen nPos, sal_Unicode c );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir     /// One of YMD,DMY,MDY if date format
406cdf0e10cSrcweir     DateFormat GetDateOrder() const;
407cdf0e10cSrcweir 
408cdf0e10cSrcweir     /** A coded value of the exact YMD combination used, if date format.
409cdf0e10cSrcweir         For example: YYYY-MM-DD => ('Y' << 16) | ('M' << 8) | 'D'
410cdf0e10cSrcweir         or: MM/YY => ('M' << 8) | 'Y'  */
411cdf0e10cSrcweir     sal_uInt32 GetExactDateOrder() const;
412cdf0e10cSrcweir 
ImpGetScan() const413cdf0e10cSrcweir     ImpSvNumberformatScan& ImpGetScan() const { return rScan; }
414cdf0e10cSrcweir 
415cdf0e10cSrcweir     // used in XML export
416cdf0e10cSrcweir     void GetConditions( SvNumberformatLimitOps& rOper1, double& rVal1,
417cdf0e10cSrcweir                         SvNumberformatLimitOps& rOper2, double& rVal2 ) const;
418cdf0e10cSrcweir     Color* GetColor( sal_uInt16 nNumFor ) const;
419cdf0e10cSrcweir     void GetNumForInfo( sal_uInt16 nNumFor, short& rScannedType,
420cdf0e10cSrcweir                     sal_Bool& bThousand, sal_uInt16& nPrecision, sal_uInt16& nAnzLeading ) const;
421cdf0e10cSrcweir 
422cdf0e10cSrcweir     // rAttr.Number not empty if NatNum attributes are to be stored
423cdf0e10cSrcweir     void GetNatNumXml(
424cdf0e10cSrcweir             ::com::sun::star::i18n::NativeNumberXmlAttributes& rAttr,
425cdf0e10cSrcweir             sal_uInt16 nNumFor ) const;
426cdf0e10cSrcweir 
427cdf0e10cSrcweir     /** @returns <TRUE/> if E,EE,R,RR,AAA,AAAA in format code of subformat
428cdf0e10cSrcweir         nNumFor (0..3) and <b>no</b> preceding calendar was specified and the
429cdf0e10cSrcweir         currently loaded calendar is "gregorian". */
IsOtherCalendar(sal_uInt16 nNumFor) const430cdf0e10cSrcweir     sal_Bool IsOtherCalendar( sal_uInt16 nNumFor ) const
431cdf0e10cSrcweir         {
432cdf0e10cSrcweir             if ( nNumFor < 4 )
433cdf0e10cSrcweir                 return ImpIsOtherCalendar( NumFor[nNumFor] );
434cdf0e10cSrcweir             return sal_False;
435cdf0e10cSrcweir         }
436cdf0e10cSrcweir 
437cdf0e10cSrcweir     /** Switches to the first non-"gregorian" calendar, but only if the current
438cdf0e10cSrcweir         calendar is "gregorian"; original calendar name and date/time returned,
439cdf0e10cSrcweir         but only if calendar switched and rOrgCalendar was empty. */
440cdf0e10cSrcweir     void SwitchToOtherCalendar( String& rOrgCalendar, double& fOrgDateTime ) const;
441cdf0e10cSrcweir 
442cdf0e10cSrcweir     /** Switches to the "gregorian" calendar, but only if the current calendar
443cdf0e10cSrcweir         is non-"gregorian" and rOrgCalendar is not empty. Thus a preceding
444cdf0e10cSrcweir         ImpSwitchToOtherCalendar() call should have been placed prior to
445cdf0e10cSrcweir         calling this method. */
446cdf0e10cSrcweir     void SwitchToGregorianCalendar( const String& rOrgCalendar, double fOrgDateTime ) const;
447cdf0e10cSrcweir 
448cdf0e10cSrcweir     /** Switches to the first specified calendar, if any, in subformat nNumFor
449cdf0e10cSrcweir         (0..3). Original calendar name and date/time returned, but only if
450cdf0e10cSrcweir         calendar switched and rOrgCalendar was empty.
451cdf0e10cSrcweir 
452cdf0e10cSrcweir         @return
453cdf0e10cSrcweir             <TRUE/> if a calendar was specified and switched to,
454cdf0e10cSrcweir             <FALSE/> else.
455cdf0e10cSrcweir      */
SwitchToSpecifiedCalendar(String & rOrgCalendar,double & fOrgDateTime,sal_uInt16 nNumFor) const456cdf0e10cSrcweir     sal_Bool SwitchToSpecifiedCalendar( String& rOrgCalendar, double& fOrgDateTime,
457cdf0e10cSrcweir             sal_uInt16 nNumFor ) const
458cdf0e10cSrcweir         {
459cdf0e10cSrcweir             if ( nNumFor < 4 )
460cdf0e10cSrcweir                 return ImpSwitchToSpecifiedCalendar( rOrgCalendar,
461cdf0e10cSrcweir                         fOrgDateTime, NumFor[nNumFor] );
462cdf0e10cSrcweir             return sal_False;
463cdf0e10cSrcweir         }
464cdf0e10cSrcweir 
465cdf0e10cSrcweir private:
466cdf0e10cSrcweir     ImpSvNumFor NumFor[4];          // Array for the 4 subformats
467cdf0e10cSrcweir     String sFormatstring;           // The format code string
468cdf0e10cSrcweir     String sComment;                // Comment, since number formatter version 6
469cdf0e10cSrcweir     double fLimit1;                 // Value for first condition
470cdf0e10cSrcweir     double fLimit2;                 // Value for second condition
471cdf0e10cSrcweir     ImpSvNumberformatScan& rScan;   // Format code scanner
472cdf0e10cSrcweir     LanguageType eLnge;             // Language/country of the format
473cdf0e10cSrcweir     SvNumberformatLimitOps eOp1;    // Operator for first condition
474cdf0e10cSrcweir     SvNumberformatLimitOps eOp2;    // Operator for second condition
475cdf0e10cSrcweir     sal_uInt16 nNewStandardDefined;     // new builtin formats as of version 6
476cdf0e10cSrcweir     short eType;                    // Type of format
477cdf0e10cSrcweir     sal_Bool bStarFlag;                 // Take *n format as ESC n
478cdf0e10cSrcweir     sal_Bool bStandard;                 // If this is a default standard format
479cdf0e10cSrcweir     sal_Bool bIsUsed;                   // Flag as used for storing
480cdf0e10cSrcweir 
481cdf0e10cSrcweir     SVL_DLLPRIVATE sal_uInt16 ImpGetNumForStringElementCount( sal_uInt16 nNumFor ) const;
482cdf0e10cSrcweir 
483cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpIsOtherCalendar( const ImpSvNumFor& rNumFor ) const;
484cdf0e10cSrcweir 
485cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpSwitchToSpecifiedCalendar( String& rOrgCalendar,
486cdf0e10cSrcweir             double& fOrgDateTime, const ImpSvNumFor& rNumFor ) const;
487cdf0e10cSrcweir 
488cdf0e10cSrcweir #ifdef _ZFORMAT_CXX     // ----- private implementation methods -----
489cdf0e10cSrcweir 
rChrCls() const490cdf0e10cSrcweir     const CharClass& rChrCls() const        { return rScan.GetChrCls(); }
rLoc() const491cdf0e10cSrcweir     const LocaleDataWrapper& rLoc() const   { return rScan.GetLoc(); }
GetCal() const492cdf0e10cSrcweir     CalendarWrapper& GetCal() const         { return rScan.GetCal(); }
GetFormatter() const493cdf0e10cSrcweir     const SvNumberFormatter& GetFormatter() const   { return *rScan.GetNumberformatter(); }
494cdf0e10cSrcweir 
495cdf0e10cSrcweir     // divide in substrings and color conditions
496cdf0e10cSrcweir     SVL_DLLPRIVATE short ImpNextSymbol( String& rString,
497cdf0e10cSrcweir                      xub_StrLen& nPos,
498cdf0e10cSrcweir                      String& sSymbol );
499cdf0e10cSrcweir 
500cdf0e10cSrcweir     // read string until ']' and strip blanks (after condition)
501cdf0e10cSrcweir     SVL_DLLPRIVATE static xub_StrLen ImpGetNumber( String& rString,
502cdf0e10cSrcweir                    xub_StrLen& nPos,
503cdf0e10cSrcweir                    String& sSymbol );
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     // get xxx of "[$-xxx]" as LanguageType, starting at and advancing position nPos
506cdf0e10cSrcweir     SVL_DLLPRIVATE static LanguageType ImpGetLanguageType( const String& rString, xub_StrLen& nPos );
507cdf0e10cSrcweir 
508cdf0e10cSrcweir     // standard number output
509cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpGetOutputStandard( double& fNumber, String& OutString );
510cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpGetOutputStdToPrecision( double& rNumber, String& rOutString, sal_uInt16 nPrecision ) const;
511cdf0e10cSrcweir     // numbers in input line
512cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpGetOutputInputLine( double fNumber, String& OutString );
513cdf0e10cSrcweir 
514cdf0e10cSrcweir     // check subcondition
515cdf0e10cSrcweir     // OP undefined => -1
516cdf0e10cSrcweir     // else 0 or 1
517cdf0e10cSrcweir     SVL_DLLPRIVATE short ImpCheckCondition(double& fNumber,
518cdf0e10cSrcweir                          double& fLimit,
519cdf0e10cSrcweir                          SvNumberformatLimitOps eOp);
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     SVL_DLLPRIVATE sal_uLong ImpGGT(sal_uLong x, sal_uLong y);
522cdf0e10cSrcweir     SVL_DLLPRIVATE sal_uLong ImpGGTRound(sal_uLong x, sal_uLong y);
523cdf0e10cSrcweir 
524cdf0e10cSrcweir     // Helper function for number strings
525cdf0e10cSrcweir     // append string symbols, insert leading 0 or ' ', or ...
526cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpNumberFill( String& sStr,
527cdf0e10cSrcweir                     double& rNumber,
528cdf0e10cSrcweir                     xub_StrLen& k,
529cdf0e10cSrcweir                     sal_uInt16& j,
530cdf0e10cSrcweir                     sal_uInt16 nIx,
531cdf0e10cSrcweir                     short eSymbolType );
532cdf0e10cSrcweir 
533cdf0e10cSrcweir     // Helper function to fill in the integer part and the group (AKA thousand) separators
534cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpNumberFillWithThousands( String& sStr,
535cdf0e10cSrcweir                                  double& rNumber,
536cdf0e10cSrcweir                                  xub_StrLen k,
537cdf0e10cSrcweir                                  sal_uInt16 j,
538cdf0e10cSrcweir                                  sal_uInt16 nIx,
539cdf0e10cSrcweir                                  sal_uInt16 nDigCnt );
540cdf0e10cSrcweir                                     // Hilfsfunktion zum Auffuellen der Vor-
541cdf0e10cSrcweir                                     // kommazahl auch mit Tausenderpunkt
542cdf0e10cSrcweir 
543cdf0e10cSrcweir     // Helper function to fill in the group (AKA thousand) separators
544cdf0e10cSrcweir     // or to skip additional digits
545cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpDigitFill( String& sStr,
546cdf0e10cSrcweir                     xub_StrLen nStart,
547cdf0e10cSrcweir                     xub_StrLen& k,
548cdf0e10cSrcweir                     sal_uInt16 nIx,
549cdf0e10cSrcweir                     xub_StrLen & nDigitCount,
550cdf0e10cSrcweir                     utl::DigitGroupingIterator & );
551cdf0e10cSrcweir 
552cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpGetDateOutput( double fNumber,
553cdf0e10cSrcweir                        sal_uInt16 nIx,
554cdf0e10cSrcweir                        String& OutString );
555cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpGetTimeOutput( double fNumber,
556cdf0e10cSrcweir                        sal_uInt16 nIx,
557cdf0e10cSrcweir                        String& OutString );
558cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpGetDateTimeOutput( double fNumber,
559cdf0e10cSrcweir                            sal_uInt16 nIx,
560cdf0e10cSrcweir                            String& OutString );
561cdf0e10cSrcweir 
562cdf0e10cSrcweir     // Switches to the "gregorian" calendar if the current calendar is
563cdf0e10cSrcweir     // non-"gregorian" and the era is a "Dummy" era of a calendar which doesn't
564cdf0e10cSrcweir     // know a "before" era (like zh_TW ROC or ja_JP Gengou). If switched and
565cdf0e10cSrcweir     // rOrgCalendar was "gregorian" the string is emptied. If rOrgCalendar was
566cdf0e10cSrcweir     // empty the previous calendar name and date/time are returned.
567cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpFallBackToGregorianCalendar( String& rOrgCalendar, double& fOrgDateTime );
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     // Append a "G" short era string of the given calendar. In the case of a
570cdf0e10cSrcweir     // Gengou calendar this is a one character abbreviation, for other
571cdf0e10cSrcweir     // calendars the XExtendedCalendar::getDisplayString() method is called.
572cdf0e10cSrcweir     SVL_DLLPRIVATE static void ImpAppendEraG( String& OutString, const CalendarWrapper& rCal,
573cdf0e10cSrcweir             sal_Int16 nNatNum );
574cdf0e10cSrcweir 
575cdf0e10cSrcweir     SVL_DLLPRIVATE sal_Bool ImpGetNumberOutput( double fNumber,
576cdf0e10cSrcweir                          sal_uInt16 nIx,
577cdf0e10cSrcweir                          String& OutString );
578cdf0e10cSrcweir 
579cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpCopyNumberformat( const SvNumberformat& rFormat );
580cdf0e10cSrcweir 
581cdf0e10cSrcweir     // normal digits or other digits, depending on ImpSvNumFor.aNatNum,
582cdf0e10cSrcweir     // [NatNum1], [NatNum2], ...
583cdf0e10cSrcweir     SVL_DLLPRIVATE String ImpGetNatNumString( const SvNumberNatNum& rNum, sal_Int32 nVal,
584cdf0e10cSrcweir             sal_uInt16 nMinDigits = 0  ) const;
585cdf0e10cSrcweir 
ImpIntToString(sal_uInt16 nIx,sal_Int32 nVal,sal_uInt16 nMinDigits=0) const586cdf0e10cSrcweir     String ImpIntToString( sal_uInt16 nIx, sal_Int32 nVal, sal_uInt16 nMinDigits = 0 ) const
587cdf0e10cSrcweir         {
588cdf0e10cSrcweir             const SvNumberNatNum& rNum = NumFor[nIx].GetNatNum();
589cdf0e10cSrcweir             if ( nMinDigits || rNum.IsComplete() )
590cdf0e10cSrcweir                 return ImpGetNatNumString( rNum, nVal, nMinDigits );
591cdf0e10cSrcweir             return String::CreateFromInt32( nVal );
592cdf0e10cSrcweir         }
593cdf0e10cSrcweir 
594cdf0e10cSrcweir     // transliterate according to NativeNumber
595cdf0e10cSrcweir     SVL_DLLPRIVATE void ImpTransliterateImpl( String& rStr, const SvNumberNatNum& rNum ) const;
596cdf0e10cSrcweir 
ImpTransliterate(String & rStr,const SvNumberNatNum & rNum) const597cdf0e10cSrcweir     void ImpTransliterate( String& rStr, const SvNumberNatNum& rNum ) const
598cdf0e10cSrcweir         {
599cdf0e10cSrcweir             if ( rNum.IsComplete() )
600cdf0e10cSrcweir                 ImpTransliterateImpl( rStr, rNum );
601cdf0e10cSrcweir         }
602cdf0e10cSrcweir 
603cdf0e10cSrcweir #endif // _ZFORMAT_CXX
604cdf0e10cSrcweir 
605cdf0e10cSrcweir };
606cdf0e10cSrcweir 
607cdf0e10cSrcweir #endif  // _ZFORMAT_HXX
608