1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <xlstyle.hxx>
21 #include <com/sun/star/awt/FontFamily.hpp>
22 #include <com/sun/star/awt/FontSlant.hpp>
23 #include <com/sun/star/awt/FontStrikeout.hpp>
24 #include <com/sun/star/awt/FontUnderline.hpp>
25 #include <com/sun/star/i18n/ScriptType.hpp>
26 #include <vcl/svapp.hxx>
27 #include <vcl/settings.hxx>
28 #include <vcl/font.hxx>
29 #include <sal/macros.h>
30 #include <sal/log.hxx>
31 #include <rtl/tencinfo.h>
32 #include <svtools/colorcfg.hxx>
33 #include <vcl/unohelp.hxx>
34 #include <editeng/svxfont.hxx>
35 #include <o3tl/unit_conversion.hxx>
36 #include <global.hxx>
37 #include <xlroot.hxx>
38 #include <xltools.hxx>
39 // Color data =================================================================
40 
41 /** Standard EGA colors, bright. */
42 #define EXC_PALETTE_EGA_COLORS_LIGHT \
43             Color(0x000000), Color(0xFFFFFF), Color(0xFF0000), Color(0x00FF00), Color(0x0000FF), Color(0xFFFF00), Color(0xFF00FF), Color(0x00FFFF)
44 /** Standard EGA colors, dark. */
45 #define EXC_PALETTE_EGA_COLORS_DARK \
46             Color(0x800000), Color(0x008000), Color(0x000080), Color(0x808000), Color(0x800080), Color(0x008080), Color(0xC0C0C0), Color(0x808080)
47 
48 /** Default color table for BIFF2. */
49 const Color spnDefColorTable2[] =
50 {
51 /*  0 */    EXC_PALETTE_EGA_COLORS_LIGHT
52 };
53 
54 /** Default color table for BIFF3/BIFF4. */
55 const Color spnDefColorTable3[] =
56 {
57 /*  0 */    EXC_PALETTE_EGA_COLORS_LIGHT,
58 /*  8 */    EXC_PALETTE_EGA_COLORS_LIGHT,
59 /* 16 */    EXC_PALETTE_EGA_COLORS_DARK
60 };
61 
62 /** Default color table for BIFF5/BIFF7. */
63 const Color spnDefColorTable5[] =
64 {
65 /*  0 */    EXC_PALETTE_EGA_COLORS_LIGHT,
66 /*  8 */    EXC_PALETTE_EGA_COLORS_LIGHT,
67 /* 16 */    EXC_PALETTE_EGA_COLORS_DARK,
68 /* 24 */    Color(0x8080FF), Color(0x802060), Color(0xFFFFC0), Color(0xA0E0E0), Color(0x600080), Color(0xFF8080), Color(0x0080C0), Color(0xC0C0FF),
69 /* 32 */    Color(0x000080), Color(0xFF00FF), Color(0xFFFF00), Color(0x00FFFF), Color(0x800080), Color(0x800000), Color(0x008080), Color(0x0000FF),
70 /* 40 */    Color(0x00CFFF), Color(0x69FFFF), Color(0xE0FFE0), Color(0xFFFF80), Color(0xA6CAF0), Color(0xDD9CB3), Color(0xB38FEE), Color(0xE3E3E3),
71 /* 48 */    Color(0x2A6FF9), Color(0x3FB8CD), Color(0x488436), Color(0x958C41), Color(0x8E5E42), Color(0xA0627A), Color(0x624FAC), Color(0x969696),
72 /* 56 */    Color(0x1D2FBE), Color(0x286676), Color(0x004500), Color(0x453E01), Color(0x6A2813), Color(0x85396A), Color(0x4A3285), Color(0x424242)
73 };
74 
75 /** Default color table for BIFF8. */
76 const Color spnDefColorTable8[] =
77 {
78 /*  0 */    EXC_PALETTE_EGA_COLORS_LIGHT,
79 /*  8 */    EXC_PALETTE_EGA_COLORS_LIGHT,
80 /* 16 */    EXC_PALETTE_EGA_COLORS_DARK,
81 /* 24 */    Color(0x9999FF), Color(0x993366), Color(0xFFFFCC), Color(0xCCFFFF), Color(0x660066), Color(0xFF8080), Color(0x0066CC), Color(0xCCCCFF),
82 /* 32 */    Color(0x000080), Color(0xFF00FF), Color(0xFFFF00), Color(0x00FFFF), Color(0x800080), Color(0x800000), Color(0x008080), Color(0x0000FF),
83 /* 40 */    Color(0x00CCFF), Color(0xCCFFFF), Color(0xCCFFCC), Color(0xFFFF99), Color(0x99CCFF), Color(0xFF99CC), Color(0xCC99FF), Color(0xFFCC99),
84 /* 48 */    Color(0x3366FF), Color(0x33CCCC), Color(0x99CC00), Color(0xFFCC00), Color(0xFF9900), Color(0xFF6600), Color(0x666699), Color(0x969696),
85 /* 56 */    Color(0x003366), Color(0x339966), Color(0x003300), Color(0x333300), Color(0x993300), Color(0x993366), Color(0x333399), Color(0x333333)
86 };
87 
88 #undef EXC_PALETTE_EGA_COLORS_LIGHT
89 #undef EXC_PALETTE_EGA_COLORS_DARK
90 
XclDefaultPalette(const XclRoot & rRoot)91 XclDefaultPalette::XclDefaultPalette( const XclRoot& rRoot ) :
92     mpnColorTable( nullptr ),
93     mnTableSize( 0 )
94 {
95     const StyleSettings& rSett = Application::GetSettings().GetStyleSettings();
96     mnWindowText = rSett.GetWindowTextColor();
97     mnWindowBack = rSett.GetWindowColor();
98     mnFaceColor = rSett.GetFaceColor();
99     // Don't use the system HelpBack and HelpText colours as it causes problems
100     // with modern gnome. This is because mnNoteText and mnNoteBack are used
101     // when colour indices ( instead of real colours ) are specified.
102     // Note: That this it is not an unusual scenario that we get the Note
103     // background specified as a real colour and the text specified as a
104     // colour index. That means the text colour would be picked from
105     // the system where the note background would be picked from a real colour.
106     // Previously the note text colour was picked from the system tooltip
107     // text colour, on modern gnome(e.g. 3) that tends to be 'white' with the
108     // default theme.
109     // Using the Libreoffice defaults ( instead of system specific colours
110     // ) lessens the chance of the one colour being an unsuitable combination
111     // because by default the note text is black and the note background is
112     // a light yellow colour ( very similar to Excel's normal defaults )
113     mnNoteText =  svtools::ColorConfig::GetDefaultColor( svtools::FONTCOLOR );
114     mnNoteBack =  svtools::ColorConfig::GetDefaultColor( svtools::CALCNOTESBACKGROUND );
115 
116     // default colors
117     switch( rRoot.GetBiff() )
118     {
119         case EXC_BIFF2:
120             mpnColorTable = spnDefColorTable2;
121             mnTableSize = SAL_N_ELEMENTS( spnDefColorTable2 );
122         break;
123         case EXC_BIFF3:
124         case EXC_BIFF4:
125             mpnColorTable = spnDefColorTable3;
126             mnTableSize = SAL_N_ELEMENTS( spnDefColorTable3 );
127         break;
128         case EXC_BIFF5:
129             mpnColorTable = spnDefColorTable5;
130             mnTableSize = SAL_N_ELEMENTS( spnDefColorTable5 );
131         break;
132         case EXC_BIFF8:
133             mpnColorTable = spnDefColorTable8;
134             mnTableSize = SAL_N_ELEMENTS( spnDefColorTable8 );
135         break;
136         default:
137             DBG_ERROR_BIFF();
138     }
139 }
140 
GetDefColor(sal_uInt16 nXclIndex) const141 Color XclDefaultPalette::GetDefColor( sal_uInt16 nXclIndex ) const
142 {
143     Color nColor;
144     if( nXclIndex < mnTableSize )
145         nColor = mpnColorTable[ nXclIndex ];
146     else switch( nXclIndex )
147     {
148         case EXC_COLOR_WINDOWTEXT3:
149         case EXC_COLOR_WINDOWTEXT:
150         case EXC_COLOR_CHWINDOWTEXT:    nColor = mnWindowText;  break;
151         case EXC_COLOR_WINDOWBACK3:
152         case EXC_COLOR_WINDOWBACK:
153         case EXC_COLOR_CHWINDOWBACK:    nColor = mnWindowBack;  break;
154         case EXC_COLOR_BUTTONBACK:      nColor = mnFaceColor;   break;
155         case EXC_COLOR_CHBORDERAUTO:    nColor = COL_BLACK;     break;  // TODO: really always black?
156         case EXC_COLOR_NOTEBACK:        nColor = mnNoteBack;    break;
157         case EXC_COLOR_NOTETEXT:        nColor = mnNoteText;    break;
158         case EXC_COLOR_FONTAUTO:        nColor = COL_AUTO;      break;
159         default:
160             SAL_WARN("sc",  "XclDefaultPalette::GetDefColor - unknown default color index: " << nXclIndex );
161             nColor = COL_AUTO;
162     }
163     return nColor;
164 }
165 
166 // Font Data ==================================================================
167 
168 namespace Awt              = ::com::sun::star::awt;
169 namespace AwtFontFamily    = Awt::FontFamily;
170 namespace AwtFontLineStyle  = Awt::FontUnderline;
171 namespace AwtFontStrikeout = Awt::FontStrikeout;
172 
XclFontData()173 XclFontData::XclFontData()
174 {
175     Clear();
176 }
177 
XclFontData(const vcl::Font & rFont)178 XclFontData::XclFontData( const vcl::Font& rFont )
179 {
180     Clear();
181     FillFromVclFont( rFont );
182 }
183 
XclFontData(const SvxFont & rFont)184 XclFontData::XclFontData( const SvxFont& rFont )
185 {
186     FillFromSvxFont( rFont );
187 }
188 
Clear()189 void XclFontData::Clear()
190 {
191     maName.clear();
192     maStyle.clear();
193     maColor = COL_AUTO;
194     mnHeight = 0;
195     mnWeight = EXC_FONTWGHT_DONTKNOW;
196     mnEscapem = EXC_FONTESC_NONE;
197     mnFamily = EXC_FONTFAM_SYSTEM;
198     mnCharSet = EXC_FONTCSET_ANSI_LATIN;
199     mnUnderline = EXC_FONTUNDERL_NONE;
200     mbItalic = mbStrikeout = mbOutline = mbShadow = false;
201 }
202 
FillFromVclFont(const vcl::Font & rFont)203 void XclFontData::FillFromVclFont( const vcl::Font& rFont )
204 {
205     maName = XclTools::GetXclFontName( rFont.GetFamilyName() );   // substitute with MS fonts
206     maStyle.clear();
207     maColor = rFont.GetColor();
208     SetScUnderline( rFont.GetUnderline() );
209     mnEscapem = EXC_FONTESC_NONE;
210     SetScHeight( rFont.GetFontSize().Height() );
211     SetScWeight( rFont.GetWeight() );
212     SetScFamily( rFont.GetFamilyType() );
213     SetFontEncoding( rFont.GetCharSet() );
214     SetScPosture( rFont.GetItalic() );
215     SetScStrikeout( rFont.GetStrikeout() );
216     mbOutline = rFont.IsOutline();
217     mbShadow = rFont.IsShadow();
218 }
219 
FillFromSvxFont(const SvxFont & rFont)220 void XclFontData::FillFromSvxFont( const SvxFont& rFont )
221 {
222     FillFromVclFont( rFont );
223     SetScEscapement( rFont.GetEscapement() );
224 }
225 
226 // *** conversion of VCL/SVX constants *** ------------------------------------
227 
GetScFamily(rtl_TextEncoding eDefTextEnc) const228 FontFamily XclFontData::GetScFamily( rtl_TextEncoding eDefTextEnc ) const
229 {
230     FontFamily eScFamily;
231     // ! format differs from Windows documentation: family is in lower nibble, pitch unknown
232     switch( mnFamily & 0x0F )
233     {
234         case EXC_FONTFAM_ROMAN:         eScFamily = FAMILY_ROMAN;       break;
235         case EXC_FONTFAM_SWISS:         eScFamily = FAMILY_SWISS;       break;
236         case EXC_FONTFAM_MODERN:        eScFamily = FAMILY_MODERN;      break;
237         case EXC_FONTFAM_SCRIPT:        eScFamily = FAMILY_SCRIPT;      break;
238         case EXC_FONTFAM_DECORATIVE:    eScFamily = FAMILY_DECORATIVE;  break;
239         default:
240             eScFamily =
241                 ((eDefTextEnc == RTL_TEXTENCODING_APPLE_ROMAN) &&
242                 (maName.equalsIgnoreAsciiCase( "Geneva" ) || maName.equalsIgnoreAsciiCase( "Chicago" ))) ?
243                 FAMILY_SWISS : FAMILY_DONTKNOW;
244     }
245     return eScFamily;
246 }
247 
GetFontEncoding() const248 rtl_TextEncoding XclFontData::GetFontEncoding() const
249 {
250     // convert Windows character set to text encoding identifier
251     return rtl_getTextEncodingFromWindowsCharset( mnCharSet );
252 }
253 
GetScPosture() const254 FontItalic XclFontData::GetScPosture() const
255 {
256     return mbItalic ? ITALIC_NORMAL : ITALIC_NONE;
257 }
258 
GetScWeight() const259 FontWeight XclFontData::GetScWeight() const
260 {
261     FontWeight eScWeight;
262 
263     if( !mnWeight )             eScWeight = WEIGHT_DONTKNOW;
264     else if( mnWeight < 150 )   eScWeight = WEIGHT_THIN;
265     else if( mnWeight < 250 )   eScWeight = WEIGHT_ULTRALIGHT;
266     else if( mnWeight < 325 )   eScWeight = WEIGHT_LIGHT;
267     else if( mnWeight < 375 )   eScWeight = WEIGHT_SEMILIGHT;
268     else if( mnWeight < 450 )   eScWeight = WEIGHT_NORMAL;
269     else if( mnWeight < 550 )   eScWeight = WEIGHT_MEDIUM;
270     else if( mnWeight < 650 )   eScWeight = WEIGHT_SEMIBOLD;
271     else if( mnWeight < 750 )   eScWeight = WEIGHT_BOLD;
272     else if( mnWeight < 850 )   eScWeight = WEIGHT_ULTRABOLD;
273     else                        eScWeight = WEIGHT_BLACK;
274 
275     return eScWeight;
276 }
277 
GetScUnderline() const278 FontLineStyle XclFontData::GetScUnderline() const
279 {
280     FontLineStyle eScUnderl = LINESTYLE_NONE;
281     switch( mnUnderline )
282     {
283         case EXC_FONTUNDERL_SINGLE:
284         case EXC_FONTUNDERL_SINGLE_ACC: eScUnderl = LINESTYLE_SINGLE;  break;
285         case EXC_FONTUNDERL_DOUBLE:
286         case EXC_FONTUNDERL_DOUBLE_ACC: eScUnderl = LINESTYLE_DOUBLE;  break;
287     }
288     return eScUnderl;
289 }
290 
GetScEscapement() const291 SvxEscapement XclFontData::GetScEscapement() const
292 {
293     SvxEscapement eScEscapem = SvxEscapement::Off;
294     switch( mnEscapem )
295     {
296         case EXC_FONTESC_SUPER: eScEscapem = SvxEscapement::Superscript;    break;
297         case EXC_FONTESC_SUB:   eScEscapem = SvxEscapement::Subscript;      break;
298     }
299     return eScEscapem;
300 }
301 
GetScStrikeout() const302 FontStrikeout XclFontData::GetScStrikeout() const
303 {
304     return mbStrikeout ? STRIKEOUT_SINGLE : STRIKEOUT_NONE;
305 }
306 
SetScHeight(sal_Int32 nTwips)307 void XclFontData::SetScHeight( sal_Int32 nTwips )
308 {
309     mnHeight = static_cast< sal_uInt16 >( ::std::min( nTwips, static_cast<sal_Int32>(0x7FFFL) ) );
310 }
311 
SetScFamily(FontFamily eScFamily)312 void XclFontData::SetScFamily( FontFamily eScFamily )
313 {
314     switch( eScFamily )
315     {
316         case FAMILY_DONTKNOW:   mnFamily = EXC_FONTFAM_DONTKNOW;    break;
317         case FAMILY_DECORATIVE: mnFamily = EXC_FONTFAM_DECORATIVE;  break;
318         case FAMILY_MODERN:     mnFamily = EXC_FONTFAM_MODERN;      break;
319         case FAMILY_ROMAN:      mnFamily = EXC_FONTFAM_ROMAN;       break;
320         case FAMILY_SCRIPT:     mnFamily = EXC_FONTFAM_SCRIPT;      break;
321         case FAMILY_SWISS:      mnFamily = EXC_FONTFAM_SWISS;       break;
322         case FAMILY_SYSTEM:     mnFamily = EXC_FONTFAM_SYSTEM;      break;
323         default:
324             OSL_FAIL( "XclFontData::SetScFamily - unknown font family" );
325             mnFamily = EXC_FONTFAM_DONTKNOW;
326     }
327 }
328 
SetFontEncoding(rtl_TextEncoding eFontEnc)329 void XclFontData::SetFontEncoding( rtl_TextEncoding eFontEnc )
330 {
331     // convert text encoding identifier to Windows character set
332     mnCharSet = rtl_getBestWindowsCharsetFromTextEncoding( eFontEnc );
333 }
334 
SetScPosture(FontItalic eScPosture)335 void XclFontData::SetScPosture( FontItalic eScPosture )
336 {
337     mbItalic = (eScPosture == ITALIC_OBLIQUE) || (eScPosture == ITALIC_NORMAL);
338 }
339 
SetScWeight(FontWeight eScWeight)340 void XclFontData::SetScWeight( FontWeight eScWeight )
341 {
342     switch( eScWeight )
343     {
344         case WEIGHT_DONTKNOW:   mnWeight = EXC_FONTWGHT_DONTKNOW;   break;
345         case WEIGHT_THIN:       mnWeight = EXC_FONTWGHT_THIN;       break;
346         case WEIGHT_ULTRALIGHT: mnWeight = EXC_FONTWGHT_ULTRALIGHT; break;
347         case WEIGHT_LIGHT:      mnWeight = EXC_FONTWGHT_LIGHT;      break;
348         case WEIGHT_SEMILIGHT:  mnWeight = EXC_FONTWGHT_SEMILIGHT;  break;
349         case WEIGHT_NORMAL:     mnWeight = EXC_FONTWGHT_NORMAL;     break;
350         case WEIGHT_MEDIUM:     mnWeight = EXC_FONTWGHT_MEDIUM;     break;
351         case WEIGHT_SEMIBOLD:   mnWeight = EXC_FONTWGHT_SEMIBOLD;   break;
352         case WEIGHT_BOLD:       mnWeight = EXC_FONTWGHT_BOLD;       break;
353         case WEIGHT_ULTRABOLD:  mnWeight = EXC_FONTWGHT_ULTRABOLD;  break;
354         case WEIGHT_BLACK:      mnWeight = EXC_FONTWGHT_BLACK;      break;
355         default:                mnWeight = EXC_FONTWGHT_NORMAL;
356     }
357 }
358 
SetScUnderline(FontLineStyle eScUnderl)359 void XclFontData::SetScUnderline( FontLineStyle eScUnderl )
360 {
361     switch( eScUnderl )
362     {
363         case LINESTYLE_NONE:
364         case LINESTYLE_DONTKNOW:    mnUnderline = EXC_FONTUNDERL_NONE;      break;
365         case LINESTYLE_DOUBLE:
366         case LINESTYLE_DOUBLEWAVE:  mnUnderline = EXC_FONTUNDERL_DOUBLE;    break;
367         default:                    mnUnderline = EXC_FONTUNDERL_SINGLE;
368     }
369 }
370 
SetScEscapement(short nScEscapem)371 void XclFontData::SetScEscapement( short nScEscapem )
372 {
373     if( nScEscapem > 0 )
374         mnEscapem = EXC_FONTESC_SUPER;
375     else if( nScEscapem < 0 )
376         mnEscapem = EXC_FONTESC_SUB;
377     else
378         mnEscapem = EXC_FONTESC_NONE;
379 }
380 
SetScStrikeout(FontStrikeout eScStrikeout)381 void XclFontData::SetScStrikeout( FontStrikeout eScStrikeout )
382 {
383     mbStrikeout =
384         (eScStrikeout == STRIKEOUT_SINGLE) || (eScStrikeout == STRIKEOUT_DOUBLE) ||
385         (eScStrikeout == STRIKEOUT_BOLD)   || (eScStrikeout == STRIKEOUT_SLASH)  ||
386         (eScStrikeout == STRIKEOUT_X);
387 }
388 
389 // *** conversion of API constants *** ----------------------------------------
390 
GetApiHeight() const391 float XclFontData::GetApiHeight() const
392 {
393     return o3tl::convert<double>(mnHeight, o3tl::Length::twip, o3tl::Length::pt);
394 }
395 
GetApiFamily() const396 sal_Int16 XclFontData::GetApiFamily() const
397 {
398     sal_Int16 nApiFamily = AwtFontFamily::DONTKNOW;
399     switch( mnFamily )
400     {
401         case FAMILY_DECORATIVE: nApiFamily = AwtFontFamily::DECORATIVE; break;
402         case FAMILY_MODERN:     nApiFamily = AwtFontFamily::MODERN;     break;
403         case FAMILY_ROMAN:      nApiFamily = AwtFontFamily::ROMAN;      break;
404         case FAMILY_SCRIPT:     nApiFamily = AwtFontFamily::SCRIPT;     break;
405         case FAMILY_SWISS:      nApiFamily = AwtFontFamily::SWISS;      break;
406         case FAMILY_SYSTEM:     nApiFamily = AwtFontFamily::SYSTEM;     break;
407     }
408     return nApiFamily;
409 }
410 
GetApiFontEncoding() const411 sal_Int16 XclFontData::GetApiFontEncoding() const
412 {
413     // API constants are equal to rtl_TextEncoding constants
414     return static_cast< sal_Int16 >( GetFontEncoding() );
415 }
416 
GetApiPosture() const417 Awt::FontSlant XclFontData::GetApiPosture() const
418 {
419     return mbItalic ? Awt::FontSlant_ITALIC : Awt::FontSlant_NONE;
420 }
421 
GetApiWeight() const422 float XclFontData::GetApiWeight() const
423 {
424     return vcl::unohelper::ConvertFontWeight( GetScWeight() );
425 }
426 
GetApiUnderline() const427 sal_Int16 XclFontData::GetApiUnderline() const
428 {
429     sal_Int16 nApiUnderl = AwtFontLineStyle::NONE;
430     switch( mnUnderline )
431     {
432         case EXC_FONTUNDERL_SINGLE:
433         case EXC_FONTUNDERL_SINGLE_ACC: nApiUnderl = AwtFontLineStyle::SINGLE;  break;
434         case EXC_FONTUNDERL_DOUBLE:
435         case EXC_FONTUNDERL_DOUBLE_ACC: nApiUnderl = AwtFontLineStyle::DOUBLE;  break;
436     }
437     return nApiUnderl;
438 }
439 
GetApiEscapement() const440 sal_Int16 XclFontData::GetApiEscapement() const
441 {
442     sal_Int16 nApiEscapem = 0;
443     switch( mnEscapem )
444     {
445         case EXC_FONTESC_SUPER: nApiEscapem = 33;   break;
446         case EXC_FONTESC_SUB:   nApiEscapem = -33;  break;
447     }
448     return nApiEscapem;
449 }
450 
GetApiStrikeout() const451 sal_Int16 XclFontData::GetApiStrikeout() const
452 {
453     return mbStrikeout ? AwtFontStrikeout::SINGLE : AwtFontStrikeout::NONE;
454 }
455 
SetApiHeight(float fPoint)456 void XclFontData::SetApiHeight( float fPoint )
457 {
458     mnHeight = std::min(o3tl::convert(fPoint, o3tl::Length::pt, o3tl::Length::twip) + 0.5, 32767.0);
459 }
460 
SetApiFamily(sal_Int16 nApiFamily)461 void XclFontData::SetApiFamily( sal_Int16 nApiFamily )
462 {
463     switch( nApiFamily )
464     {
465         case AwtFontFamily::DECORATIVE: mnFamily = FAMILY_DECORATIVE;   break;
466         case AwtFontFamily::MODERN:     mnFamily = FAMILY_MODERN;       break;
467         case AwtFontFamily::ROMAN:      mnFamily = FAMILY_ROMAN;        break;
468         case AwtFontFamily::SCRIPT:     mnFamily = FAMILY_SCRIPT;       break;
469         case AwtFontFamily::SWISS:      mnFamily = FAMILY_SWISS;        break;
470         case AwtFontFamily::SYSTEM:     mnFamily = FAMILY_SYSTEM;       break;
471         default:                        mnFamily = FAMILY_DONTKNOW;
472     }
473 }
474 
SetApiPosture(Awt::FontSlant eApiPosture)475 void XclFontData::SetApiPosture( Awt::FontSlant eApiPosture )
476 {
477     mbItalic =
478         (eApiPosture == Awt::FontSlant_OBLIQUE) ||
479         (eApiPosture == Awt::FontSlant_ITALIC) ||
480         (eApiPosture == Awt::FontSlant_REVERSE_OBLIQUE) ||
481         (eApiPosture == Awt::FontSlant_REVERSE_ITALIC);
482 }
483 
SetApiWeight(float fApiWeight)484 void XclFontData::SetApiWeight( float fApiWeight )
485 {
486     SetScWeight( vcl::unohelper::ConvertFontWeight( fApiWeight ) );
487 }
488 
SetApiUnderline(sal_Int16 nApiUnderl)489 void XclFontData::SetApiUnderline( sal_Int16 nApiUnderl )
490 {
491     switch( nApiUnderl )
492     {
493         case AwtFontLineStyle::NONE:
494         case AwtFontLineStyle::DONTKNOW:    mnUnderline = EXC_FONTUNDERL_NONE;      break;
495         case AwtFontLineStyle::DOUBLE:
496         case AwtFontLineStyle::DOUBLEWAVE:  mnUnderline = EXC_FONTUNDERL_DOUBLE;    break;
497         default:                            mnUnderline = EXC_FONTUNDERL_SINGLE;
498     }
499 }
500 
SetApiEscapement(sal_Int16 nApiEscapem)501 void XclFontData::SetApiEscapement( sal_Int16 nApiEscapem )
502 {
503     if( nApiEscapem > 0 )
504         mnEscapem = EXC_FONTESC_SUPER;
505     else if( nApiEscapem < 0 )
506         mnEscapem = EXC_FONTESC_SUB;
507     else
508         mnEscapem = EXC_FONTESC_NONE;
509 }
510 
SetApiStrikeout(sal_Int16 nApiStrikeout)511 void XclFontData::SetApiStrikeout( sal_Int16 nApiStrikeout )
512 {
513     mbStrikeout =
514         (nApiStrikeout != AwtFontStrikeout::NONE) &&
515         (nApiStrikeout != AwtFontStrikeout::DONTKNOW);
516 }
517 
operator ==(const XclFontData & rLeft,const XclFontData & rRight)518 bool operator==( const XclFontData& rLeft, const XclFontData& rRight )
519 {
520     return
521         (rLeft.mnHeight    == rRight.mnHeight)    &&
522         (rLeft.mnWeight    == rRight.mnWeight)    &&
523         (rLeft.mnUnderline == rRight.mnUnderline) &&
524         (rLeft.maColor     == rRight.maColor)     &&
525         (rLeft.mnEscapem   == rRight.mnEscapem)   &&
526         (rLeft.mnFamily    == rRight.mnFamily)    &&
527         (rLeft.mnCharSet   == rRight.mnCharSet)   &&
528         (rLeft.mbItalic    == rRight.mbItalic)    &&
529         (rLeft.mbStrikeout == rRight.mbStrikeout) &&
530         (rLeft.mbOutline   == rRight.mbOutline)   &&
531         (rLeft.mbShadow    == rRight.mbShadow)    &&
532         (rLeft.maName      == rRight.maName);
533 }
534 
535 namespace {
536 
537 /** Property names for common font settings. */
538 const char *const sppcPropNamesChCommon[] =
539 {
540     "CharUnderline", "CharStrikeout", "CharColor", "CharContoured", "CharShadowed", nullptr
541 };
542 /** Property names for Western font settings. */
543 const char *const sppcPropNamesChWstrn[] =
544 {
545     "CharFontName", "CharHeight", "CharPosture", "CharWeight", nullptr
546 };
547 /** Property names for Asian font settings. */
548 const char *const sppcPropNamesChAsian[] =
549 {
550     "CharFontNameAsian", "CharHeightAsian", "CharPostureAsian", "CharWeightAsian", nullptr
551 };
552 /** Property names for Complex font settings. */
553 const char *const sppcPropNamesChCmplx[] =
554 {
555     "CharFontNameComplex", "CharHeightComplex", "CharPostureComplex", "CharWeightComplex", nullptr
556 };
557 /** Property names for escapement. */
558 const char *const sppcPropNamesChEscapement[] =
559 {
560     "CharEscapement", "CharEscapementHeight", nullptr
561 };
562 const sal_Int8 EXC_API_ESC_HEIGHT           = 58;   /// Default escapement font height.
563 
564 /** Property names for Western font settings without font name. */
565 const char *const *const sppcPropNamesChWstrnNoName = sppcPropNamesChWstrn + 1;
566 /** Property names for Asian font settings without font name. */
567 const char *const *const sppcPropNamesChAsianNoName = sppcPropNamesChAsian + 1;
568 /** Property names for Complex font settings without font name. */
569 const char *const *const sppcPropNamesChCmplxNoName = sppcPropNamesChCmplx + 1;
570 
571 /** Property names for font settings in form controls. */
572 const char *const sppcPropNamesControl[] =
573 {
574     "FontName", "FontFamily", "FontCharset", "FontHeight", "FontSlant",
575     "FontWeight", "FontLineStyle", "FontStrikeout", "TextColor", nullptr
576 };
577 
578 /** Inserts all passed API font settings into the font data object. */
lclSetApiFontSettings(XclFontData & rFontData,const OUString & rApiFontName,float fApiHeight,float fApiWeight,Awt::FontSlant eApiPosture,sal_Int16 nApiUnderl,sal_Int16 nApiStrikeout)579 void lclSetApiFontSettings( XclFontData& rFontData,
580         const OUString& rApiFontName, float fApiHeight, float fApiWeight,
581         Awt::FontSlant eApiPosture, sal_Int16 nApiUnderl, sal_Int16 nApiStrikeout )
582 {
583     rFontData.maName = XclTools::GetXclFontName( rApiFontName );
584     rFontData.SetApiHeight( fApiHeight );
585     rFontData.SetApiWeight( fApiWeight );
586     rFontData.SetApiPosture( eApiPosture );
587     rFontData.SetApiUnderline( nApiUnderl );
588     rFontData.SetApiStrikeout( nApiStrikeout );
589 }
590 
591 /** Writes script dependent properties to a font property set helper. */
lclWriteChartFont(ScfPropertySet & rPropSet,ScfPropSetHelper & rHlpName,ScfPropSetHelper & rHlpNoName,const XclFontData & rFontData,bool bHasFontName)592 void lclWriteChartFont( ScfPropertySet& rPropSet,
593         ScfPropSetHelper& rHlpName, ScfPropSetHelper& rHlpNoName,
594         const XclFontData& rFontData, bool bHasFontName )
595 {
596     // select the font helper
597     ScfPropSetHelper& rPropSetHlp = bHasFontName ? rHlpName : rHlpNoName;
598     // initialize the font helper (must be called before writing any properties)
599     rPropSetHlp.InitializeWrite();
600     // write font name
601     if( bHasFontName )
602         rPropSetHlp << rFontData.maName;
603     // write remaining properties
604     rPropSetHlp << rFontData.GetApiHeight() << rFontData.GetApiPosture() << rFontData.GetApiWeight();
605     // write properties to property set
606     rPropSetHlp.WriteToPropertySet( rPropSet );
607 }
608 
609 } // namespace
610 
XclFontPropSetHelper()611 XclFontPropSetHelper::XclFontPropSetHelper() :
612     maHlpChCommon( sppcPropNamesChCommon ),
613     maHlpChWstrn( sppcPropNamesChWstrn ),
614     maHlpChAsian( sppcPropNamesChAsian ),
615     maHlpChCmplx( sppcPropNamesChCmplx ),
616     maHlpChWstrnNoName( sppcPropNamesChWstrnNoName ),
617     maHlpChAsianNoName( sppcPropNamesChAsianNoName ),
618     maHlpChCmplxNoName( sppcPropNamesChCmplxNoName ),
619     maHlpChEscapement( sppcPropNamesChEscapement ),
620     maHlpControl( sppcPropNamesControl )
621 {
622 }
623 
ReadFontProperties(XclFontData & rFontData,const ScfPropertySet & rPropSet,XclFontPropSetType eType,sal_Int16 nScript)624 void XclFontPropSetHelper::ReadFontProperties( XclFontData& rFontData,
625         const ScfPropertySet& rPropSet, XclFontPropSetType eType, sal_Int16 nScript )
626 {
627     switch( eType )
628     {
629         case EXC_FONTPROPSET_CHART:
630         {
631             OUString aApiFontName;
632             float fApiHeight, fApiWeight;
633             sal_Int16 nApiUnderl = 0, nApiStrikeout = 0;
634             Awt::FontSlant eApiPosture;
635 
636             // read script type dependent properties
637             ScfPropSetHelper& rPropSetHlp = GetChartHelper( nScript );
638             rPropSetHlp.ReadFromPropertySet( rPropSet );
639             rPropSetHlp >> aApiFontName >> fApiHeight >> eApiPosture >> fApiWeight;
640             // read common properties
641             maHlpChCommon.ReadFromPropertySet( rPropSet );
642             maHlpChCommon   >> nApiUnderl
643                             >> nApiStrikeout
644                             >> rFontData.maColor
645                             >> rFontData.mbOutline
646                             >> rFontData.mbShadow;
647 
648             // convert API property values to Excel settings
649             lclSetApiFontSettings( rFontData, aApiFontName,
650                 fApiHeight, fApiWeight, eApiPosture, nApiUnderl, nApiStrikeout );
651 
652             // font escapement
653             sal_Int16 nApiEscapement = 0;
654             sal_Int8 nApiEscHeight = 0;
655             maHlpChEscapement.ReadFromPropertySet( rPropSet );
656             maHlpChEscapement.ReadFromPropertySet( rPropSet );
657             maHlpChEscapement.ReadFromPropertySet( rPropSet );
658             maHlpChEscapement >> nApiEscapement >> nApiEscHeight;
659             rFontData.SetApiEscapement( nApiEscapement );
660         }
661         break;
662 
663         case EXC_FONTPROPSET_CONTROL:
664         {
665             OUString aApiFontName;
666             float fApiHeight(0.0), fApiWeight(0.0);
667             sal_Int16 nApiFamily(0), nApiCharSet(0), nApiPosture(0), nApiUnderl(0), nApiStrikeout(0);
668 
669             // read font properties
670             maHlpControl.ReadFromPropertySet( rPropSet );
671             maHlpControl    >> aApiFontName
672                             >> nApiFamily
673                             >> nApiCharSet
674                             >> fApiHeight
675                             >> nApiPosture
676                             >> fApiWeight
677                             >> nApiUnderl
678                             >> nApiStrikeout
679                             >> rFontData.maColor;
680 
681             // convert API property values to Excel settings
682             Awt::FontSlant eApiPosture = static_cast< Awt::FontSlant >( nApiPosture );
683             lclSetApiFontSettings( rFontData, aApiFontName,
684                 fApiHeight, fApiWeight, eApiPosture, nApiUnderl, nApiStrikeout );
685             rFontData.SetApiFamily( nApiFamily );
686             rFontData.SetFontEncoding( nApiCharSet );
687         }
688         break;
689     }
690 }
691 
WriteFontProperties(ScfPropertySet & rPropSet,XclFontPropSetType eType,const XclFontData & rFontData,bool bHasWstrn,bool bHasAsian,bool bHasCmplx,const Color * pFontColor)692 void XclFontPropSetHelper::WriteFontProperties(
693         ScfPropertySet& rPropSet, XclFontPropSetType eType,
694         const XclFontData& rFontData, bool bHasWstrn, bool bHasAsian, bool bHasCmplx,
695         const Color* pFontColor )
696 {
697     switch( eType )
698     {
699         case EXC_FONTPROPSET_CHART:
700         {
701             // write common properties
702             maHlpChCommon.InitializeWrite();
703             const Color& rColor = pFontColor ? *pFontColor : rFontData.maColor;
704             maHlpChCommon   << rFontData.GetApiUnderline()
705                             << rFontData.GetApiStrikeout()
706                             << rColor
707                             << rFontData.mbOutline
708                             << rFontData.mbShadow;
709             maHlpChCommon.WriteToPropertySet( rPropSet );
710 
711             // write script type dependent properties
712             lclWriteChartFont( rPropSet, maHlpChWstrn, maHlpChWstrnNoName, rFontData, bHasWstrn );
713             lclWriteChartFont( rPropSet, maHlpChAsian, maHlpChAsianNoName, rFontData, bHasAsian );
714             lclWriteChartFont( rPropSet, maHlpChCmplx, maHlpChCmplxNoName, rFontData, bHasCmplx );
715 
716             // font escapement
717             if( rFontData.GetScEscapement() != SvxEscapement::Off )
718             {
719                 maHlpChEscapement.InitializeWrite();
720                 maHlpChEscapement << rFontData.GetApiEscapement() << EXC_API_ESC_HEIGHT;
721                 maHlpChEscapement.WriteToPropertySet( rPropSet );
722             }
723         }
724         break;
725 
726         case EXC_FONTPROPSET_CONTROL:
727         {
728             maHlpControl.InitializeWrite();
729             maHlpControl    << rFontData.maName
730                             << rFontData.GetApiFamily()
731                             << rFontData.GetApiFontEncoding()
732                             << static_cast< sal_Int16 >( rFontData.GetApiHeight() + 0.5 )
733                             << rFontData.GetApiPosture()
734                             << rFontData.GetApiWeight()
735                             << rFontData.GetApiUnderline()
736                             << rFontData.GetApiStrikeout()
737                             << rFontData.maColor;
738             maHlpControl.WriteToPropertySet( rPropSet );
739         }
740         break;
741     }
742 }
743 
GetChartHelper(sal_Int16 nScript)744 ScfPropSetHelper& XclFontPropSetHelper::GetChartHelper( sal_Int16 nScript )
745 {
746     namespace ApiScriptType = ::com::sun::star::i18n::ScriptType;
747     switch( nScript )
748     {
749         case ApiScriptType::LATIN:      return maHlpChWstrn;
750         case ApiScriptType::ASIAN:      return maHlpChAsian;
751         case ApiScriptType::COMPLEX:    return maHlpChCmplx;
752         default:    OSL_FAIL( "XclFontPropSetHelper::GetChartHelper - unknown script type" );
753     }
754     return maHlpChWstrn;
755 }
756 
757 // Number formats =============================================================
758 
759 namespace {
760 
761 /** Special number format index describing a reused format. */
762 const NfIndexTableOffset PRV_NF_INDEX_REUSE = NF_INDEX_TABLE_ENTRIES;
763 
764 /** German primary language not defined, LANGUAGE_GERMAN belongs to Germany. */
765 constexpr LanguageType PRV_LANGUAGE_GERMAN_PRIM = primary(LANGUAGE_GERMAN);
766 /** French primary language not defined, LANGUAGE_FRENCH belongs to France. */
767 constexpr LanguageType PRV_LANGUAGE_FRENCH_PRIM = primary(LANGUAGE_FRENCH);
768 /** Parent language identifier for Asian languages. */
769 constexpr LanguageType PRV_LANGUAGE_ASIAN_PRIM = primary(LANGUAGE_CHINESE);
770 
771 /** Stores the number format used in Calc for an Excel built-in number format. */
772 struct XclBuiltInFormat
773 {
774     sal_uInt16          mnXclNumFmt;    /// Excel built-in index.
775     const char*         mpFormat;       /// Format string, may be 0 (meOffset used then).
776     NfIndexTableOffset  meOffset;       /// SvNumberFormatter format index, if mpFormat==0.
777     sal_uInt16          mnXclReuseFmt;  /// Use this Excel format, if meOffset==PRV_NF_INDEX_REUSE.
778 };
779 
780 /** Defines a literal Excel built-in number format. */
781 #define EXC_NUMFMT_STRING( nXclNumFmt, pcUtf8 ) \
782     { nXclNumFmt, pcUtf8, NF_NUMBER_STANDARD, 0 }
783 
784 /** Defines an Excel built-in number format that maps to an own built-in format. */
785 #define EXC_NUMFMT_OFFSET( nXclNumFmt, eOffset ) \
786     { nXclNumFmt, nullptr, eOffset, 0 }
787 
788 /** Defines an Excel built-in number format that is the same as the specified. */
789 #define EXC_NUMFMT_REUSE( nXclNumFmt, nXclReuse ) \
790     { nXclNumFmt, nullptr, PRV_NF_INDEX_REUSE, nXclReuse }
791 
792 /** Terminates an Excel built-in number format table. */
793 #define EXC_NUMFMT_ENDTABLE() \
794     { EXC_FORMAT_NOTFOUND, nullptr, NF_NUMBER_STANDARD, 0 }
795 
796 // Currency unit characters
797 #define UTF8_BAHT       "\340\270\277"
798 #define UTF8_EURO       "\342\202\254"
799 #define UTF8_POUND_UK   "\302\243"
800 #define UTF8_SHEQEL     "\342\202\252"
801 #define UTF8_WON        "\357\277\246"
802 #define UTF8_YEN_CS     "\357\277\245"
803 #define UTF8_YEN_JP     "\302\245"
804 
805 // Japanese/Chinese date/time characters
806 #define UTF8_CJ_YEAR    "\345\271\264"
807 #define UTF8_CJ_MON     "\346\234\210"
808 #define UTF8_CJ_DAY     "\346\227\245"
809 #define UTF8_CJ_HOUR    "\346\231\202"
810 #define UTF8_CJ_MIN     "\345\210\206"
811 #define UTF8_CJ_SEC     "\347\247\222"
812 
813 // Chinese Simplified date/time characters
814 #define UTF8_CS_HOUR    "\346\227\266"
815 
816 // Korean date/time characters
817 #define UTF8_KO_YEAR    "\353\205\204"
818 #define UTF8_KO_MON     "\354\233\224"
819 #define UTF8_KO_DAY     "\354\235\274"
820 #define UTF8_KO_HOUR    "\354\213\234"
821 #define UTF8_KO_MIN     "\353\266\204"
822 #define UTF8_KO_SEC     "\354\264\210"
823 
824 /** Default number format table. Last parent of all other tables, used for unknown languages. */
825 const XclBuiltInFormat spBuiltInFormats_DONTKNOW[] =
826 {
827     EXC_NUMFMT_OFFSET(   0, NF_NUMBER_STANDARD ),       // General
828     EXC_NUMFMT_OFFSET(   1, NF_NUMBER_INT ),            // 0
829     EXC_NUMFMT_OFFSET(   2, NF_NUMBER_DEC2 ),           // 0.00
830     EXC_NUMFMT_OFFSET(   3, NF_NUMBER_1000INT ),        // #,##0
831     EXC_NUMFMT_OFFSET(   4, NF_NUMBER_1000DEC2 ),       // #,##0.00
832     // 5...8 contained in file
833     EXC_NUMFMT_OFFSET(   9, NF_PERCENT_INT ),           // 0%
834     EXC_NUMFMT_OFFSET(  10, NF_PERCENT_DEC2 ),          // 0.00%
835     EXC_NUMFMT_OFFSET(  11, NF_SCIENTIFIC_000E00 ),     // 0.00E+00
836     EXC_NUMFMT_OFFSET(  12, NF_FRACTION_1D ),            // # ?/?
837     EXC_NUMFMT_OFFSET(  13, NF_FRACTION_2D ),            // # ??/??
838 
839     // 14...22 date and time formats
840     EXC_NUMFMT_OFFSET(  14, NF_DATE_SYS_DDMMYYYY ),
841     EXC_NUMFMT_OFFSET(  15, NF_DATE_SYS_DMMMYY ),
842     EXC_NUMFMT_OFFSET(  16, NF_DATE_SYS_DDMMM ),
843     EXC_NUMFMT_OFFSET(  17, NF_DATE_SYS_MMYY ),
844     EXC_NUMFMT_OFFSET(  18, NF_TIME_HHMMAMPM ),
845     EXC_NUMFMT_OFFSET(  19, NF_TIME_HHMMSSAMPM ),
846     EXC_NUMFMT_OFFSET(  20, NF_TIME_HHMM ),
847     EXC_NUMFMT_OFFSET(  21, NF_TIME_HHMMSS ),
848     EXC_NUMFMT_OFFSET(  22, NF_DATETIME_SYSTEM_SHORT_HHMM ),
849 
850     // 23...36 international formats
851     EXC_NUMFMT_REUSE(   23, 0 ),
852     EXC_NUMFMT_REUSE(   24, 0 ),
853     EXC_NUMFMT_REUSE(   25, 0 ),
854     EXC_NUMFMT_REUSE(   26, 0 ),
855     EXC_NUMFMT_REUSE(   27, 14 ),
856     EXC_NUMFMT_REUSE(   28, 14 ),
857     EXC_NUMFMT_REUSE(   29, 14 ),
858     EXC_NUMFMT_REUSE(   30, 14 ),
859     EXC_NUMFMT_REUSE(   31, 14 ),
860     EXC_NUMFMT_REUSE(   32, 21 ),
861     EXC_NUMFMT_REUSE(   33, 21 ),
862     EXC_NUMFMT_REUSE(   34, 21 ),
863     EXC_NUMFMT_REUSE(   35, 21 ),
864     EXC_NUMFMT_REUSE(   36, 14 ),
865 
866     // 37...44 accounting formats
867     // 41...44 contained in file
868     EXC_NUMFMT_STRING(  37, "#,##0;-#,##0" ),
869     EXC_NUMFMT_STRING(  38, "#,##0;[RED]-#,##0" ),
870     EXC_NUMFMT_STRING(  39, "#,##0.00;-#,##0.00" ),
871     EXC_NUMFMT_STRING(  40, "#,##0.00;[RED]-#,##0.00" ),
872 
873     // 45...49 more special formats
874     EXC_NUMFMT_STRING(  45, "mm:ss" ),
875     EXC_NUMFMT_STRING(  46, "[h]:mm:ss" ),
876     EXC_NUMFMT_STRING(  47, "mm:ss.0" ),
877     EXC_NUMFMT_STRING(  48, "##0.0E+0" ),
878     EXC_NUMFMT_OFFSET(  49, NF_TEXT ),
879 
880     // 50...81 international formats
881     EXC_NUMFMT_REUSE(   50, 14 ),
882     EXC_NUMFMT_REUSE(   51, 14 ),
883     EXC_NUMFMT_REUSE(   52, 14 ),
884     EXC_NUMFMT_REUSE(   53, 14 ),
885     EXC_NUMFMT_REUSE(   54, 14 ),
886     EXC_NUMFMT_REUSE(   55, 14 ),
887     EXC_NUMFMT_REUSE(   56, 14 ),
888     EXC_NUMFMT_REUSE(   57, 14 ),
889     EXC_NUMFMT_REUSE(   58, 14 ),
890     EXC_NUMFMT_REUSE(   59, 1 ),
891     EXC_NUMFMT_REUSE(   60, 2 ),
892     EXC_NUMFMT_REUSE(   61, 3 ),
893     EXC_NUMFMT_REUSE(   62, 4 ),
894     EXC_NUMFMT_REUSE(   67, 9 ),
895     EXC_NUMFMT_REUSE(   68, 10 ),
896     EXC_NUMFMT_REUSE(   69, 12 ),
897     EXC_NUMFMT_REUSE(   70, 13 ),
898     EXC_NUMFMT_REUSE(   71, 14 ),
899     EXC_NUMFMT_REUSE(   72, 14 ),
900     EXC_NUMFMT_REUSE(   73, 15 ),
901     EXC_NUMFMT_REUSE(   74, 16 ),
902     EXC_NUMFMT_REUSE(   75, 17 ),
903     EXC_NUMFMT_REUSE(   76, 20 ),
904     EXC_NUMFMT_REUSE(   77, 21 ),
905     EXC_NUMFMT_REUSE(   78, 22 ),
906     EXC_NUMFMT_REUSE(   79, 45 ),
907     EXC_NUMFMT_REUSE(   80, 46 ),
908     EXC_NUMFMT_REUSE(   81, 47 ),
909 
910     // 82...163 not used, must not occur in a file (Excel may crash)
911 
912     EXC_NUMFMT_ENDTABLE()
913 };
914 
915 // ENGLISH --------------------------------------------------------------------
916 
917 /** Base table for English locales. */
918 const XclBuiltInFormat spBuiltInFormats_ENGLISH[] =
919 {
920     EXC_NUMFMT_STRING(  15, "DD-MMM-YY" ),
921     EXC_NUMFMT_STRING(  16, "DD-MMM" ),
922     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
923     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
924     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
925     EXC_NUMFMT_STRING(  22, "DD/MM/YYYY hh:mm" ),
926     EXC_NUMFMT_ENDTABLE()
927 };
928 
929 const XclBuiltInFormat spBuiltInFormats_ENGLISH_UK[] =
930 {
931     EXC_NUMFMT_STRING(  63, UTF8_POUND_UK "#,##0;-" UTF8_POUND_UK "#,##0" ),
932     EXC_NUMFMT_STRING(  64, UTF8_POUND_UK "#,##0;[RED]-" UTF8_POUND_UK "#,##0" ),
933     EXC_NUMFMT_STRING(  65, UTF8_POUND_UK "#,##0.00;-" UTF8_POUND_UK "#,##0.00" ),
934     EXC_NUMFMT_STRING(  66, UTF8_POUND_UK "#,##0.00;[RED]-" UTF8_POUND_UK "#,##0.00" ),
935     EXC_NUMFMT_ENDTABLE()
936 };
937 
938 const XclBuiltInFormat spBuiltInFormats_ENGLISH_EIRE[] =
939 {
940     EXC_NUMFMT_STRING(  63, UTF8_EURO "#,##0;-" UTF8_EURO "#,##0" ),
941     EXC_NUMFMT_STRING(  64, UTF8_EURO "#,##0;[RED]-" UTF8_EURO "#,##0" ),
942     EXC_NUMFMT_STRING(  65, UTF8_EURO "#,##0.00;-" UTF8_EURO "#,##0.00" ),
943     EXC_NUMFMT_STRING(  66, UTF8_EURO "#,##0.00;[RED]-" UTF8_EURO "#,##0.00" ),
944     EXC_NUMFMT_ENDTABLE()
945 };
946 
947 const XclBuiltInFormat spBuiltInFormats_ENGLISH_US[] =
948 {
949     EXC_NUMFMT_STRING(  14, "M/D/YYYY" ),
950     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
951     EXC_NUMFMT_STRING(  16, "D-MMM" ),
952     EXC_NUMFMT_STRING(  20, "h:mm" ),
953     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
954     EXC_NUMFMT_STRING(  22, "M/D/YYYY h:mm" ),
955     EXC_NUMFMT_STRING(  37, "#,##0_);(#,##0)" ),
956     EXC_NUMFMT_STRING(  38, "#,##0_);[RED](#,##0)" ),
957     EXC_NUMFMT_STRING(  39, "#,##0.00_);(#,##0.00)" ),
958     EXC_NUMFMT_STRING(  40, "#,##0.00_);[RED](#,##0.00)" ),
959     EXC_NUMFMT_STRING(  63, "$#,##0_);($#,##0)" ),
960     EXC_NUMFMT_STRING(  64, "$#,##0_);[RED]($#,##0)" ),
961     EXC_NUMFMT_STRING(  65, "$#,##0.00_);($#,##0.00)" ),
962     EXC_NUMFMT_STRING(  66, "$#,##0.00_);[RED]($#,##0.00)" ),
963     EXC_NUMFMT_ENDTABLE()
964 };
965 
966 const XclBuiltInFormat spBuiltInFormats_ENGLISH_CAN[] =
967 {
968     EXC_NUMFMT_STRING(  20, "h:mm" ),
969     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
970     EXC_NUMFMT_STRING(  22, "DD/MM/YYYY h:mm" ),
971     EXC_NUMFMT_STRING(  63, "$#,##0;-$#,##0" ),
972     EXC_NUMFMT_STRING(  64, "$#,##0;[RED]-$#,##0" ),
973     EXC_NUMFMT_STRING(  65, "$#,##0.00;-$#,##0.00" ),
974     EXC_NUMFMT_STRING(  66, "$#,##0.00;[RED]-$#,##0.00" ),
975     EXC_NUMFMT_ENDTABLE()
976 };
977 
978 const XclBuiltInFormat spBuiltInFormats_ENGLISH_AUS[] =
979 {
980     EXC_NUMFMT_STRING(  14, "D/MM/YYYY" ),
981     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
982     EXC_NUMFMT_STRING(  16, "D-MMM" ),
983     EXC_NUMFMT_STRING(  20, "h:mm" ),
984     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
985     EXC_NUMFMT_STRING(  22, "D/MM/YYYY h:mm" ),
986     EXC_NUMFMT_STRING(  63, "$#,##0;-$#,##0" ),
987     EXC_NUMFMT_STRING(  64, "$#,##0;[RED]-$#,##0" ),
988     EXC_NUMFMT_STRING(  65, "$#,##0.00;-$#,##0.00" ),
989     EXC_NUMFMT_STRING(  66, "$#,##0.00;[RED]-$#,##0.00" ),
990     EXC_NUMFMT_ENDTABLE()
991 };
992 
993 const XclBuiltInFormat spBuiltInFormats_ENGLISH_SAFRICA[] =
994 {
995     EXC_NUMFMT_STRING(  14, "YYYY/MM/DD" ),
996     EXC_NUMFMT_OFFSET(  18, NF_TIME_HHMMAMPM ),
997     EXC_NUMFMT_OFFSET(  19, NF_TIME_HHMMSSAMPM ),
998     EXC_NUMFMT_STRING(  22, "YYYY/MM/DD hh:mm" ),
999     EXC_NUMFMT_STRING(  63, "\\R #,##0;\\R -#,##0" ),
1000     EXC_NUMFMT_STRING(  64, "\\R #,##0;[RED]\\R -#,##0" ),
1001     EXC_NUMFMT_STRING(  65, "\\R #,##0.00;\\R -#,##0.00" ),
1002     EXC_NUMFMT_STRING(  66, "\\R #,##0.00;[RED]\\R -#,##0.00" ),
1003     EXC_NUMFMT_ENDTABLE()
1004 };
1005 
1006 // FRENCH ---------------------------------------------------------------------
1007 
1008 /** Base table for French locales. */
1009 const XclBuiltInFormat spBuiltInFormats_FRENCH[] =
1010 {
1011     EXC_NUMFMT_STRING(  15, "DD-MMM-YY" ),
1012     EXC_NUMFMT_STRING(  16, "DD-MMM" ),
1013     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1014     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1015     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1016     EXC_NUMFMT_ENDTABLE()
1017 };
1018 
1019 const XclBuiltInFormat spBuiltInFormats_FRENCH_FRANCE[] =
1020 {
1021     EXC_NUMFMT_STRING(  22, "DD/MM/YYYY hh:mm" ),
1022     EXC_NUMFMT_STRING(  37, "#,##0\\ _" UTF8_EURO ";-#,##0\\ _" UTF8_EURO ),
1023     EXC_NUMFMT_STRING(  38, "#,##0\\ _" UTF8_EURO ";[RED]-#,##0\\ _" UTF8_EURO ),
1024     EXC_NUMFMT_STRING(  39, "#,##0.00\\ _" UTF8_EURO ";-#,##0.00\\ _" UTF8_EURO ),
1025     EXC_NUMFMT_STRING(  40, "#,##0.00\\ _" UTF8_EURO ";[RED]-#,##0.00\\ _" UTF8_EURO ),
1026     EXC_NUMFMT_STRING(  63, "#,##0\\ " UTF8_EURO ";-#,##0\\ " UTF8_EURO ),
1027     EXC_NUMFMT_STRING(  64, "#,##0\\ " UTF8_EURO ";[RED]-#,##0\\ " UTF8_EURO ),
1028     EXC_NUMFMT_STRING(  65, "#,##0.00\\ " UTF8_EURO ";-#,##0.00\\ " UTF8_EURO ),
1029     EXC_NUMFMT_STRING(  66, "#,##0.00\\ " UTF8_EURO ";[RED]-#,##0.00\\ " UTF8_EURO ),
1030     EXC_NUMFMT_ENDTABLE()
1031 };
1032 
1033 const XclBuiltInFormat spBuiltInFormats_FRENCH_CANADIAN[] =
1034 {
1035     EXC_NUMFMT_STRING(  22, "YYYY-MM-DD hh:mm" ),
1036     EXC_NUMFMT_STRING(  37, "#,##0\\ _$_-;#,##0\\ _$-" ),
1037     EXC_NUMFMT_STRING(  38, "#,##0\\ _$_-;[RED]#,##0\\ _$-" ),
1038     EXC_NUMFMT_STRING(  39, "#,##0.00\\ _$_-;#,##0.00\\ _$-" ),
1039     EXC_NUMFMT_STRING(  40, "#,##0.00\\ _$_-;[RED]#,##0.00\\ _$-" ),
1040     EXC_NUMFMT_STRING(  63, "#,##0\\ $_-;#,##0\\ $-" ),
1041     EXC_NUMFMT_STRING(  64, "#,##0\\ $_-;[RED]#,##0\\ $-" ),
1042     EXC_NUMFMT_STRING(  65, "#,##0.00\\ $_-;#,##0.00\\ $-" ),
1043     EXC_NUMFMT_STRING(  66, "#,##0.00\\ $_-;[RED]#,##0.00\\ $-" ),
1044     EXC_NUMFMT_ENDTABLE()
1045 };
1046 
1047 const XclBuiltInFormat spBuiltInFormats_FRENCH_SWISS[] =
1048 {
1049     EXC_NUMFMT_STRING(  15, "DD.MMM.YY" ),
1050     EXC_NUMFMT_STRING(  16, "DD.MMM" ),
1051     EXC_NUMFMT_STRING(  17, "MMM.YY" ),
1052     EXC_NUMFMT_STRING(  22, "DD.MM.YYYY hh:mm" ),
1053     EXC_NUMFMT_STRING(  63, "\"SFr. \"#,##0;\"SFr. \"-#,##0" ),
1054     EXC_NUMFMT_STRING(  64, "\"SFr. \"#,##0;[RED]\"SFr. \"-#,##0" ),
1055     EXC_NUMFMT_STRING(  65, "\"SFr. \"#,##0.00;\"SFr. \"-#,##0.00" ),
1056     EXC_NUMFMT_STRING(  66, "\"SFr. \"#,##0.00;[RED]\"SFr. \"-#,##0.00" ),
1057     EXC_NUMFMT_ENDTABLE()
1058 };
1059 
1060 const XclBuiltInFormat spBuiltInFormats_FRENCH_BELGIAN[] =
1061 {
1062     EXC_NUMFMT_STRING(  14, "D/MM/YYYY" ),
1063     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
1064     EXC_NUMFMT_STRING(  16, "D-MMM" ),
1065     EXC_NUMFMT_STRING(  20, "h:mm" ),
1066     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
1067     EXC_NUMFMT_STRING(  22, "D/MM/YYYY h:mm" ),
1068     EXC_NUMFMT_ENDTABLE()
1069 };
1070 
1071 // GERMAN ---------------------------------------------------------------------
1072 
1073 /** Base table for German locales. */
1074 const XclBuiltInFormat spBuiltInFormats_GERMAN[] =
1075 {
1076     EXC_NUMFMT_STRING(  15, "DD. MMM YY" ),
1077     EXC_NUMFMT_STRING(  16, "DD. MMM" ),
1078     EXC_NUMFMT_STRING(  17, "MMM YY" ),
1079     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1080     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1081     EXC_NUMFMT_STRING(  22, "DD.MM.YYYY hh:mm" ),
1082     EXC_NUMFMT_ENDTABLE()
1083 };
1084 
1085 const XclBuiltInFormat spBuiltInFormats_GERMAN_GERMANY[] =
1086 {
1087     EXC_NUMFMT_STRING(  37, "#,##0 _" UTF8_EURO ";-#,##0 _" UTF8_EURO ),
1088     EXC_NUMFMT_STRING(  38, "#,##0 _" UTF8_EURO ";[RED]-#,##0 _" UTF8_EURO ),
1089     EXC_NUMFMT_STRING(  39, "#,##0.00 _" UTF8_EURO ";-#,##0.00 _" UTF8_EURO ),
1090     EXC_NUMFMT_STRING(  40, "#,##0.00 _" UTF8_EURO ";[RED]-#,##0.00 _" UTF8_EURO ),
1091     EXC_NUMFMT_STRING(  63, "#,##0 " UTF8_EURO ";-#,##0 " UTF8_EURO ),
1092     EXC_NUMFMT_STRING(  64, "#,##0 " UTF8_EURO ";[RED]-#,##0 " UTF8_EURO ),
1093     EXC_NUMFMT_STRING(  65, "#,##0.00 " UTF8_EURO ";-#,##0.00 " UTF8_EURO ),
1094     EXC_NUMFMT_STRING(  66, "#,##0.00 " UTF8_EURO ";[RED]-#,##0.00 " UTF8_EURO ),
1095     EXC_NUMFMT_ENDTABLE()
1096 };
1097 
1098 const XclBuiltInFormat spBuiltInFormats_GERMAN_AUSTRIAN[] =
1099 {
1100     EXC_NUMFMT_STRING(  15, "DD.MMM.YY" ),
1101     EXC_NUMFMT_STRING(  16, "DD.MMM" ),
1102     EXC_NUMFMT_STRING(  17, "MMM.YY" ),
1103     EXC_NUMFMT_STRING(  63, UTF8_EURO " #,##0;-" UTF8_EURO " #,##0" ),
1104     EXC_NUMFMT_STRING(  64, UTF8_EURO " #,##0;[RED]-" UTF8_EURO " #,##0" ),
1105     EXC_NUMFMT_STRING(  65, UTF8_EURO " #,##0.00;-" UTF8_EURO " #,##0.00" ),
1106     EXC_NUMFMT_STRING(  66, UTF8_EURO " #,##0.00;[RED]-" UTF8_EURO " #,##0.00" ),
1107     EXC_NUMFMT_ENDTABLE()
1108 };
1109 
1110 const XclBuiltInFormat spBuiltInFormats_GERMAN_SWISS[] =
1111 {
1112     EXC_NUMFMT_STRING(  63, "\"SFr. \"#,##0;\"SFr. \"-#,##0" ),
1113     EXC_NUMFMT_STRING(  64, "\"SFr. \"#,##0;[RED]\"SFr. \"-#,##0" ),
1114     EXC_NUMFMT_STRING(  65, "\"SFr. \"#,##0.00;\"SFr. \"-#,##0.00" ),
1115     EXC_NUMFMT_STRING(  66, "\"SFr. \"#,##0.00;[RED]\"SFr. \"-#,##0.00" ),
1116     EXC_NUMFMT_ENDTABLE()
1117 };
1118 
1119 const XclBuiltInFormat spBuiltInFormats_GERMAN_LUXEMBOURG[] =
1120 {
1121     EXC_NUMFMT_STRING(  15, "DD.MMM.YY" ),
1122     EXC_NUMFMT_STRING(  16, "DD.MMM" ),
1123     EXC_NUMFMT_STRING(  17, "MMM.YY" ),
1124     EXC_NUMFMT_STRING(  37, "#,##0 _" UTF8_EURO ";-#,##0 _" UTF8_EURO ),
1125     EXC_NUMFMT_STRING(  38, "#,##0 _" UTF8_EURO ";[RED]-#,##0 _" UTF8_EURO ),
1126     EXC_NUMFMT_STRING(  39, "#,##0.00 _" UTF8_EURO ";-#,##0.00 _" UTF8_EURO ),
1127     EXC_NUMFMT_STRING(  40, "#,##0.00 _" UTF8_EURO ";[RED]-#,##0.00 _" UTF8_EURO ),
1128     EXC_NUMFMT_STRING(  63, "#,##0 " UTF8_EURO ";-#,##0 " UTF8_EURO ),
1129     EXC_NUMFMT_STRING(  64, "#,##0 " UTF8_EURO ";[RED]-#,##0 " UTF8_EURO ),
1130     EXC_NUMFMT_STRING(  65, "#,##0.00 " UTF8_EURO ";-#,##0.00 " UTF8_EURO ),
1131     EXC_NUMFMT_STRING(  66, "#,##0.00 " UTF8_EURO ";[RED]-#,##0.00 " UTF8_EURO ),
1132     EXC_NUMFMT_ENDTABLE()
1133 };
1134 
1135 const XclBuiltInFormat spBuiltInFormats_GERMAN_LIECHTENSTEIN[] =
1136 {
1137     EXC_NUMFMT_STRING(  63, "\"CHF \"#,##0;\"CHF \"-#,##0" ),
1138     EXC_NUMFMT_STRING(  64, "\"CHF \"#,##0;[RED]\"CHF \"-#,##0" ),
1139     EXC_NUMFMT_STRING(  65, "\"CHF \"#,##0.00;\"CHF \"-#,##0.00" ),
1140     EXC_NUMFMT_STRING(  66, "\"CHF \"#,##0.00;[RED]\"CHF \"-#,##0.00" ),
1141     EXC_NUMFMT_ENDTABLE()
1142 };
1143 
1144 // ITALIAN --------------------------------------------------------------------
1145 
1146 const XclBuiltInFormat spBuiltInFormats_ITALIAN_ITALY[] =
1147 {
1148     EXC_NUMFMT_STRING(  15, "DD-MMM-YY" ),
1149     EXC_NUMFMT_STRING(  16, "DD-MMM" ),
1150     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1151     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1152     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1153     EXC_NUMFMT_STRING(  20, "h:mm" ),
1154     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
1155     EXC_NUMFMT_STRING(  22, "DD/MM/YYYY h:mm" ),
1156     EXC_NUMFMT_STRING(  63, UTF8_EURO " #,##0;-" UTF8_EURO " #,##0" ),
1157     EXC_NUMFMT_STRING(  64, UTF8_EURO " #,##0;[RED]-" UTF8_EURO " #,##0" ),
1158     EXC_NUMFMT_STRING(  65, UTF8_EURO " #,##0.00;-" UTF8_EURO " #,##0.00" ),
1159     EXC_NUMFMT_STRING(  66, UTF8_EURO " #,##0.00;[RED]-" UTF8_EURO " #,##0.00" ),
1160     EXC_NUMFMT_ENDTABLE()
1161 };
1162 
1163 const XclBuiltInFormat spBuiltInFormats_ITALIAN_SWISS[] =
1164 {
1165     EXC_NUMFMT_STRING(  15, "DD.MMM.YY" ),
1166     EXC_NUMFMT_STRING(  16, "DD.MMM" ),
1167     EXC_NUMFMT_STRING(  17, "MMM.YY" ),
1168     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1169     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1170     EXC_NUMFMT_STRING(  22, "DD.MM.YYYY hh:mm" ),
1171     EXC_NUMFMT_STRING(  63, "\"SFr. \"#,##0;\"SFr. \"-#,##0" ),
1172     EXC_NUMFMT_STRING(  64, "\"SFr. \"#,##0;[RED]\"SFr. \"-#,##0" ),
1173     EXC_NUMFMT_STRING(  65, "\"SFr. \"#,##0.00;\"SFr. \"-#,##0.00" ),
1174     EXC_NUMFMT_STRING(  66, "\"SFr. \"#,##0.00;[RED]\"SFr. \"-#,##0.00" ),
1175     EXC_NUMFMT_ENDTABLE()
1176 };
1177 
1178 // SWEDISH --------------------------------------------------------------------
1179 
1180 const XclBuiltInFormat spBuiltInFormats_SWEDISH_SWEDEN[] =
1181 {
1182     EXC_NUMFMT_STRING(  15, "DD-MMM-YY" ),
1183     EXC_NUMFMT_STRING(  16, "DD-MMM" ),
1184     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1185     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1186     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1187     EXC_NUMFMT_STRING(  22, "YYYY-MM-DD hh:mm" ),
1188     EXC_NUMFMT_STRING(  37, "#,##0 _k_r;-#,##0 _k_r" ),
1189     EXC_NUMFMT_STRING(  38, "#,##0 _k_r;[RED]-#,##0 _k_r" ),
1190     EXC_NUMFMT_STRING(  39, "#,##0.00 _k_r;-#,##0.00 _k_r" ),
1191     EXC_NUMFMT_STRING(  40, "#,##0.00 _k_r;[RED]-#,##0.00 _k_r" ),
1192     EXC_NUMFMT_STRING(  63, "#,##0 \"kr\";-#,##0 \"kr\"" ),
1193     EXC_NUMFMT_STRING(  64, "#,##0 \"kr\";[RED]-#,##0 \"kr\"" ),
1194     EXC_NUMFMT_STRING(  65, "#,##0.00 \"kr\";-#,##0.00 \"kr\"" ),
1195     EXC_NUMFMT_STRING(  66, "#,##0.00 \"kr\";[RED]-#,##0.00 \"kr\"" ),
1196     EXC_NUMFMT_ENDTABLE()
1197 };
1198 
1199 const XclBuiltInFormat spBuiltInFormats_SWEDISH_FINLAND[] =
1200 {
1201     EXC_NUMFMT_STRING(   9, "0 %" ),
1202     EXC_NUMFMT_STRING(  10, "0.00 %" ),
1203     EXC_NUMFMT_STRING(  15, "DD.MMM.YY" ),
1204     EXC_NUMFMT_STRING(  16, "DD.MMM" ),
1205     EXC_NUMFMT_STRING(  17, "MMM.YY" ),
1206     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1207     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1208     EXC_NUMFMT_STRING(  22, "D.M.YYYY hh:mm" ),
1209     EXC_NUMFMT_STRING(  37, "#,##0 _" UTF8_EURO ";-#,##0 _" UTF8_EURO ),
1210     EXC_NUMFMT_STRING(  38, "#,##0 _" UTF8_EURO ";[RED]-#,##0 _" UTF8_EURO ),
1211     EXC_NUMFMT_STRING(  39, "#,##0.00 _" UTF8_EURO ";-#,##0.00 _" UTF8_EURO ),
1212     EXC_NUMFMT_STRING(  40, "#,##0.00 _" UTF8_EURO ";[RED]-#,##0.00 _" UTF8_EURO ),
1213     EXC_NUMFMT_STRING(  63, "#,##0 " UTF8_EURO ";-#,##0 " UTF8_EURO ),
1214     EXC_NUMFMT_STRING(  64, "#,##0 " UTF8_EURO ";[RED]-#,##0 " UTF8_EURO ),
1215     EXC_NUMFMT_STRING(  65, "#,##0.00 " UTF8_EURO ";-#,##0.00 " UTF8_EURO ),
1216     EXC_NUMFMT_STRING(  66, "#,##0.00 " UTF8_EURO ";[RED]-#,##0.00 " UTF8_EURO ),
1217     EXC_NUMFMT_ENDTABLE()
1218 };
1219 
1220 // ASIAN ----------------------------------------------------------------------
1221 
1222 /** Base table for Asian locales. */
1223 const XclBuiltInFormat spBuiltInFormats_ASIAN[] =
1224 {
1225     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1226     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1227     EXC_NUMFMT_STRING(  20, "h:mm" ),
1228     EXC_NUMFMT_STRING(  21, "h:mm:ss" ),
1229     EXC_NUMFMT_STRING(  23, "$#,##0_);($#,##0)" ),
1230     EXC_NUMFMT_STRING(  24, "$#,##0_);[RED]($#,##0)" ),
1231     EXC_NUMFMT_STRING(  25, "$#,##0.00_);($#,##0.00)" ),
1232     EXC_NUMFMT_STRING(  26, "$#,##0.00_);[RED]($#,##0.00)" ),
1233     EXC_NUMFMT_REUSE(   29, 28 ),
1234     EXC_NUMFMT_REUSE(   36, 27 ),
1235     EXC_NUMFMT_REUSE(   50, 27 ),
1236     EXC_NUMFMT_REUSE(   51, 28 ),
1237     EXC_NUMFMT_REUSE(   52, 34 ),
1238     EXC_NUMFMT_REUSE(   53, 35 ),
1239     EXC_NUMFMT_REUSE(   54, 28 ),
1240     EXC_NUMFMT_REUSE(   55, 34 ),
1241     EXC_NUMFMT_REUSE(   56, 35 ),
1242     EXC_NUMFMT_REUSE(   57, 27 ),
1243     EXC_NUMFMT_REUSE(   58, 28 ),
1244     EXC_NUMFMT_ENDTABLE()
1245 };
1246 
1247 const XclBuiltInFormat spBuiltInFormats_JAPANESE[] =
1248 {
1249     EXC_NUMFMT_STRING(  14, "YYYY/M/D" ),
1250     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
1251     EXC_NUMFMT_STRING(  16, "D-MMM" ),
1252     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1253     EXC_NUMFMT_STRING(  22, "YYYY/M/D h:mm" ),
1254     EXC_NUMFMT_STRING(  27, "[$-0411]GE.M.D" ),
1255     EXC_NUMFMT_STRING(  28, "[$-0411]GGGE" UTF8_CJ_YEAR "M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1256     EXC_NUMFMT_STRING(  30, "[$-0411]M/D/YY" ),
1257     EXC_NUMFMT_STRING(  31, "[$-0411]YYYY" UTF8_CJ_YEAR "M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1258     EXC_NUMFMT_STRING(  32, "[$-0411]h" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN ),
1259     EXC_NUMFMT_STRING(  33, "[$-0411]h" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN "ss" UTF8_CJ_SEC ),
1260     EXC_NUMFMT_STRING(  34, "[$-0411]YYYY" UTF8_CJ_YEAR "M" UTF8_CJ_MON ),
1261     EXC_NUMFMT_STRING(  35, "[$-0411]M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1262     EXC_NUMFMT_STRING(  63, UTF8_YEN_JP "#,##0;-" UTF8_YEN_JP "#,##0" ),
1263     EXC_NUMFMT_STRING(  64, UTF8_YEN_JP "#,##0;[RED]-" UTF8_YEN_JP "#,##0" ),
1264     EXC_NUMFMT_STRING(  65, UTF8_YEN_JP "#,##0.00;-" UTF8_YEN_JP "#,##0.00" ),
1265     EXC_NUMFMT_STRING(  66, UTF8_YEN_JP "#,##0.00;[RED]-" UTF8_YEN_JP "#,##0.00" ),
1266     EXC_NUMFMT_ENDTABLE()
1267 };
1268 
1269 const XclBuiltInFormat spBuiltInFormats_KOREAN[] =
1270 {
1271     EXC_NUMFMT_STRING(  14, "YYYY-MM-DD" ),
1272     EXC_NUMFMT_STRING(  15, "DD-MMM-YY" ),
1273     EXC_NUMFMT_STRING(  16, "DD-MMM" ),
1274     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1275     EXC_NUMFMT_STRING(  22, "YYYY-MM-DD h:mm" ),
1276     EXC_NUMFMT_STRING(  27, "[$-0412]YYYY" UTF8_CJ_YEAR " MM" UTF8_CJ_MON " DD" UTF8_CJ_DAY ),
1277     EXC_NUMFMT_STRING(  28, "[$-0412]MM-DD" ),
1278     EXC_NUMFMT_STRING(  30, "[$-0412]MM-DD-YY" ),
1279     EXC_NUMFMT_STRING(  31, "[$-0412]YYYY" UTF8_KO_YEAR " MM" UTF8_KO_MON " DD" UTF8_KO_DAY ),
1280     EXC_NUMFMT_STRING(  32, "[$-0412]h" UTF8_KO_HOUR " mm" UTF8_KO_MIN ),
1281     EXC_NUMFMT_STRING(  33, "[$-0412]h" UTF8_KO_HOUR " mm" UTF8_KO_MIN " ss" UTF8_KO_SEC ),
1282     EXC_NUMFMT_STRING(  34, "[$-0412]YYYY\"/\"MM\"/\"DD" ),
1283     EXC_NUMFMT_STRING(  35, "[$-0412]YYYY-MM-DD" ),
1284     EXC_NUMFMT_STRING(  63, UTF8_WON "#,##0;-" UTF8_WON "#,##0" ),
1285     EXC_NUMFMT_STRING(  64, UTF8_WON "#,##0;[RED]-" UTF8_WON "#,##0" ),
1286     EXC_NUMFMT_STRING(  65, UTF8_WON "#,##0.00;-" UTF8_WON "#,##0.00" ),
1287     EXC_NUMFMT_STRING(  66, UTF8_WON "#,##0.00;[RED]-" UTF8_WON "#,##0.00" ),
1288     EXC_NUMFMT_ENDTABLE()
1289 };
1290 
1291 const XclBuiltInFormat spBuiltInFormats_CHINESE_SIMPLIFIED[] =
1292 {
1293     EXC_NUMFMT_STRING(  14, "YYYY-M-D" ),
1294     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
1295     EXC_NUMFMT_STRING(  16, "D-MMM" ),
1296     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1297     EXC_NUMFMT_STRING(  22, "YYYY-M-D h:mm" ),
1298     EXC_NUMFMT_STRING(  27, "[$-0804]YYYY" UTF8_CJ_YEAR "M" UTF8_CJ_MON ),
1299     EXC_NUMFMT_STRING(  28, "[$-0804]M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1300     EXC_NUMFMT_STRING(  30, "[$-0804]M-D-YY" ),
1301     EXC_NUMFMT_STRING(  31, "[$-0804]YYYY" UTF8_CJ_YEAR "M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1302     EXC_NUMFMT_STRING(  32, "[$-0804]h" UTF8_CS_HOUR "mm" UTF8_CJ_MIN ),
1303     EXC_NUMFMT_STRING(  33, "[$-0804]h" UTF8_CS_HOUR "mm" UTF8_CJ_MIN "ss" UTF8_CJ_SEC ),
1304     EXC_NUMFMT_STRING(  34, "[$-0804]AM/PMh" UTF8_CS_HOUR "mm" UTF8_CJ_MIN ),
1305     EXC_NUMFMT_STRING(  35, "[$-0804]AM/PMh" UTF8_CS_HOUR "mm" UTF8_CJ_MIN "ss" UTF8_CJ_SEC ),
1306     EXC_NUMFMT_REUSE(   52, 27 ),
1307     EXC_NUMFMT_REUSE(   53, 28 ),
1308     EXC_NUMFMT_STRING(  63, UTF8_YEN_CS "#,##0;-" UTF8_YEN_CS "#,##0" ),
1309     EXC_NUMFMT_STRING(  64, UTF8_YEN_CS "#,##0;[RED]-" UTF8_YEN_CS "#,##0" ),
1310     EXC_NUMFMT_STRING(  65, UTF8_YEN_CS "#,##0.00;-" UTF8_YEN_CS "#,##0.00" ),
1311     EXC_NUMFMT_STRING(  66, UTF8_YEN_CS "#,##0.00;[RED]-" UTF8_YEN_CS "#,##0.00" ),
1312     EXC_NUMFMT_ENDTABLE()
1313 };
1314 
1315 const XclBuiltInFormat spBuiltInFormats_CHINESE_TRADITIONAL[] =
1316 {
1317     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
1318     EXC_NUMFMT_STRING(  16, "D-MMM" ),
1319     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1320     EXC_NUMFMT_STRING(  18, "hh:mm AM/PM" ),
1321     EXC_NUMFMT_STRING(  19, "hh:mm:ss AM/PM" ),
1322     EXC_NUMFMT_OFFSET(  20, NF_TIME_HHMM ),
1323     EXC_NUMFMT_OFFSET(  21, NF_TIME_HHMMSS ),
1324     EXC_NUMFMT_STRING(  22, "YYYY/M/D hh:mm" ),
1325     EXC_NUMFMT_STRING(  23, "US$#,##0_);(US$#,##0)" ),
1326     EXC_NUMFMT_STRING(  24, "US$#,##0_);[RED](US$#,##0)" ),
1327     EXC_NUMFMT_STRING(  25, "US$#,##0.00_);(US$#,##0.00)" ),
1328     EXC_NUMFMT_STRING(  26, "US$#,##0.00_);[RED](US$#,##0.00)" ),
1329     EXC_NUMFMT_STRING(  27, "[$-0404]E/M/D" ),
1330     EXC_NUMFMT_STRING(  28, "[$-0404]E" UTF8_CJ_YEAR "M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1331     EXC_NUMFMT_STRING(  30, "[$-0404]M/D/YY" ),
1332     EXC_NUMFMT_STRING(  31, "[$-0404]YYYY" UTF8_CJ_YEAR "M" UTF8_CJ_MON "D" UTF8_CJ_DAY ),
1333     EXC_NUMFMT_STRING(  32, "[$-0404]hh" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN ),
1334     EXC_NUMFMT_STRING(  33, "[$-0404]hh" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN "ss" UTF8_CJ_SEC ),
1335     EXC_NUMFMT_STRING(  34, "[$-0404]AM/PMhh" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN ),
1336     EXC_NUMFMT_STRING(  35, "[$-0404]AM/PMhh" UTF8_CJ_HOUR "mm" UTF8_CJ_MIN "ss" UTF8_CJ_SEC ),
1337     EXC_NUMFMT_STRING(  63, "$#,##0;-$#,##0" ),
1338     EXC_NUMFMT_STRING(  64, "$#,##0;[RED]-$#,##0" ),
1339     EXC_NUMFMT_STRING(  65, "$#,##0.00;-$#,##0.00" ),
1340     EXC_NUMFMT_STRING(  66, "$#,##0.00;[RED]-$#,##0.00" ),
1341     EXC_NUMFMT_ENDTABLE()
1342 };
1343 
1344 // OTHER ----------------------------------------------------------------------
1345 
1346 const XclBuiltInFormat spBuiltInFormats_HEBREW[] =
1347 {
1348     EXC_NUMFMT_STRING(  15, "DD-MMMM-YY" ),
1349     EXC_NUMFMT_STRING(  16, "DD-MMMM" ),
1350     EXC_NUMFMT_STRING(  17, "MMMM-YY" ),
1351     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1352     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1353     EXC_NUMFMT_STRING(  63, UTF8_SHEQEL " #,##0;" UTF8_SHEQEL " -#,##0" ),
1354     EXC_NUMFMT_STRING(  64, UTF8_SHEQEL " #,##0;[RED]" UTF8_SHEQEL " -#,##0" ),
1355     EXC_NUMFMT_STRING(  65, UTF8_SHEQEL " #,##0.00;" UTF8_SHEQEL " -#,##0.00" ),
1356     EXC_NUMFMT_STRING(  66, UTF8_SHEQEL " #,##0.00;[RED]" UTF8_SHEQEL " -#,##0.00" ),
1357     EXC_NUMFMT_ENDTABLE()
1358 };
1359 
1360 const XclBuiltInFormat spBuiltInFormats_THAI[] =
1361 {
1362     EXC_NUMFMT_STRING(  14, "D/M/YYYY" ),
1363     EXC_NUMFMT_STRING(  15, "D-MMM-YY" ),
1364     EXC_NUMFMT_STRING(  16, "D-MMM" ),
1365     EXC_NUMFMT_STRING(  17, "MMM-YY" ),
1366     EXC_NUMFMT_STRING(  18, "h:mm AM/PM" ),
1367     EXC_NUMFMT_STRING(  19, "h:mm:ss AM/PM" ),
1368     EXC_NUMFMT_STRING(  22, "D/M/YYYY h:mm" ),
1369     EXC_NUMFMT_STRING(  59, "t0" ),
1370     EXC_NUMFMT_STRING(  60, "t0.00" ),
1371     EXC_NUMFMT_STRING(  61, "t#,##0" ),
1372     EXC_NUMFMT_STRING(  62, "t#,##0.00" ),
1373     EXC_NUMFMT_STRING(  63, "t" UTF8_BAHT "#,##0_);t(" UTF8_BAHT "#,##0)" ),
1374     EXC_NUMFMT_STRING(  64, "t" UTF8_BAHT "#,##0_);[RED]t(" UTF8_BAHT "#,##0)" ),
1375     EXC_NUMFMT_STRING(  65, "t" UTF8_BAHT "#,##0.00_);t(" UTF8_BAHT "#,##0.00)" ),
1376     EXC_NUMFMT_STRING(  66, "t" UTF8_BAHT "#,##0.00_);[RED]t(" UTF8_BAHT "#,##0.00)" ),
1377     EXC_NUMFMT_STRING(  67, "t0%" ),
1378     EXC_NUMFMT_STRING(  68, "t0.00%" ),
1379     EXC_NUMFMT_STRING(  69, "t# ?/?" ),
1380     EXC_NUMFMT_STRING(  70, "t# ?\?/?\?" ),
1381     EXC_NUMFMT_STRING(  71, "tD/M/EE" ),
1382     EXC_NUMFMT_STRING(  72, "tD-MMM-E" ),
1383     EXC_NUMFMT_STRING(  73, "tD-MMM" ),
1384     EXC_NUMFMT_STRING(  74, "tMMM-E" ),
1385     EXC_NUMFMT_STRING(  75, "th:mm" ),
1386     EXC_NUMFMT_STRING(  76, "th:mm:ss" ),
1387     EXC_NUMFMT_STRING(  77, "tD/M/EE h:mm" ),
1388     EXC_NUMFMT_STRING(  78, "tmm:ss" ),
1389     EXC_NUMFMT_STRING(  79, "t[h]:mm:ss" ),
1390     EXC_NUMFMT_STRING(  80, "tmm:ss.0" ),
1391     EXC_NUMFMT_STRING(  81, "D/M/E" ),
1392     EXC_NUMFMT_ENDTABLE()
1393 };
1394 
1395 #undef EXC_NUMFMT_ENDTABLE
1396 #undef EXC_NUMFMT_REUSE
1397 #undef EXC_NUMFMT_OFFSET
1398 #undef EXC_NUMFMT_STRING
1399 
1400 /** Specifies a number format table for a specific language. */
1401 struct XclBuiltInFormatTable
1402 {
1403     LanguageType        meLanguage;         /// The language of this table.
1404     LanguageType        meParentLang;       /// The language of the parent table.
1405     const XclBuiltInFormat* mpFormats;      /// The number format table.
1406 };
1407 
1408 const XclBuiltInFormatTable spBuiltInFormatTables[] =
1409 {   //  language                        parent language             format table
1410     {   LANGUAGE_DONTKNOW,              LANGUAGE_NONE,              spBuiltInFormats_DONTKNOW               },
1411 
1412     {   LANGUAGE_ENGLISH,               LANGUAGE_DONTKNOW,          spBuiltInFormats_ENGLISH                },
1413     {   LANGUAGE_ENGLISH_UK,            LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_UK             },
1414     {   LANGUAGE_ENGLISH_EIRE,          LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_EIRE           },
1415     {   LANGUAGE_ENGLISH_US,            LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_US             },
1416     {   LANGUAGE_ENGLISH_CAN,           LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_CAN            },
1417     {   LANGUAGE_ENGLISH_AUS,           LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_AUS            },
1418     {   LANGUAGE_ENGLISH_SAFRICA,       LANGUAGE_ENGLISH,           spBuiltInFormats_ENGLISH_SAFRICA        },
1419     {   LANGUAGE_ENGLISH_NZ,            LANGUAGE_ENGLISH_AUS,       nullptr                                       },
1420 
1421     {   PRV_LANGUAGE_FRENCH_PRIM,       LANGUAGE_DONTKNOW,          spBuiltInFormats_FRENCH                 },
1422     {   LANGUAGE_FRENCH,                PRV_LANGUAGE_FRENCH_PRIM,   spBuiltInFormats_FRENCH_FRANCE          },
1423     {   LANGUAGE_FRENCH_CANADIAN,       PRV_LANGUAGE_FRENCH_PRIM,   spBuiltInFormats_FRENCH_CANADIAN        },
1424     {   LANGUAGE_FRENCH_SWISS,          PRV_LANGUAGE_FRENCH_PRIM,   spBuiltInFormats_FRENCH_SWISS           },
1425     {   LANGUAGE_FRENCH_BELGIAN,        LANGUAGE_FRENCH,            spBuiltInFormats_FRENCH_BELGIAN         },
1426     {   LANGUAGE_FRENCH_LUXEMBOURG,     LANGUAGE_FRENCH,            nullptr                                       },
1427     {   LANGUAGE_FRENCH_MONACO,         LANGUAGE_FRENCH,            nullptr                                       },
1428 
1429     {   PRV_LANGUAGE_GERMAN_PRIM,       LANGUAGE_DONTKNOW,          spBuiltInFormats_GERMAN                 },
1430     {   LANGUAGE_GERMAN,                PRV_LANGUAGE_GERMAN_PRIM,   spBuiltInFormats_GERMAN_GERMANY         },
1431     {   LANGUAGE_GERMAN_AUSTRIAN,       PRV_LANGUAGE_GERMAN_PRIM,   spBuiltInFormats_GERMAN_AUSTRIAN        },
1432     {   LANGUAGE_GERMAN_SWISS,          PRV_LANGUAGE_GERMAN_PRIM,   spBuiltInFormats_GERMAN_SWISS           },
1433     {   LANGUAGE_GERMAN_LUXEMBOURG,     PRV_LANGUAGE_GERMAN_PRIM,   spBuiltInFormats_GERMAN_LUXEMBOURG      },
1434     {   LANGUAGE_GERMAN_LIECHTENSTEIN,  PRV_LANGUAGE_GERMAN_PRIM,   spBuiltInFormats_GERMAN_LIECHTENSTEIN   },
1435 
1436     {   LANGUAGE_ITALIAN,               LANGUAGE_DONTKNOW,          spBuiltInFormats_ITALIAN_ITALY          },
1437     {   LANGUAGE_ITALIAN_SWISS,         LANGUAGE_DONTKNOW,          spBuiltInFormats_ITALIAN_SWISS          },
1438 
1439     {   LANGUAGE_SWEDISH,               LANGUAGE_DONTKNOW,          spBuiltInFormats_SWEDISH_SWEDEN         },
1440     {   LANGUAGE_SWEDISH_FINLAND,       LANGUAGE_DONTKNOW,          spBuiltInFormats_SWEDISH_FINLAND        },
1441 
1442     {   PRV_LANGUAGE_ASIAN_PRIM,        LANGUAGE_DONTKNOW,          spBuiltInFormats_ASIAN                  },
1443     {   LANGUAGE_JAPANESE,              PRV_LANGUAGE_ASIAN_PRIM,    spBuiltInFormats_JAPANESE               },
1444     {   LANGUAGE_KOREAN,                PRV_LANGUAGE_ASIAN_PRIM,    spBuiltInFormats_KOREAN                 },
1445     {   LANGUAGE_CHINESE_SIMPLIFIED,    PRV_LANGUAGE_ASIAN_PRIM,    spBuiltInFormats_CHINESE_SIMPLIFIED     },
1446     {   LANGUAGE_CHINESE_TRADITIONAL,   PRV_LANGUAGE_ASIAN_PRIM,    spBuiltInFormats_CHINESE_TRADITIONAL    },
1447 
1448     {   LANGUAGE_HEBREW,                LANGUAGE_DONTKNOW,          spBuiltInFormats_HEBREW                 },
1449     {   LANGUAGE_THAI,                  LANGUAGE_DONTKNOW,          spBuiltInFormats_THAI                   }
1450 };
1451 
1452 } // namespace
1453 
XclNumFmtBuffer(const XclRoot & rRoot)1454 XclNumFmtBuffer::XclNumFmtBuffer( const XclRoot& rRoot ) :
1455     meSysLang( rRoot.GetSysLanguage() ),
1456     mnStdScNumFmt( rRoot.GetFormatter().GetStandardIndex( ScGlobal::eLnge ) )
1457 {
1458     // *** insert default formats (BIFF5+ only)***
1459 
1460     if( rRoot.GetBiff() >= EXC_BIFF5 )
1461         InsertBuiltinFormats();
1462 }
1463 
InitializeImport()1464 void XclNumFmtBuffer::InitializeImport()
1465 {
1466     maFmtMap.clear();
1467 }
1468 
InsertFormat(sal_uInt16 nXclNumFmt,const OUString & rFormat)1469 void XclNumFmtBuffer::InsertFormat( sal_uInt16 nXclNumFmt, const OUString& rFormat )
1470 {
1471     XclNumFmt& rNumFmt = maFmtMap[ nXclNumFmt ];
1472     rNumFmt.maFormat = rFormat;
1473     // #i62053# rFormat may be an empty string, meOffset must be initialized
1474     rNumFmt.meOffset = NF_NUMBER_STANDARD;
1475     rNumFmt.meLanguage = LANGUAGE_SYSTEM;
1476 }
1477 
InsertBuiltinFormats()1478 void XclNumFmtBuffer::InsertBuiltinFormats()
1479 {
1480     // build a map containing tables for all languages
1481     typedef ::std::map< LanguageType, const XclBuiltInFormatTable* > XclBuiltInMap;
1482     XclBuiltInMap aBuiltInMap;
1483     for(const auto &rTable : spBuiltInFormatTables)
1484         aBuiltInMap[ rTable.meLanguage ] = &rTable;
1485 
1486     // build a list of table pointers for the current language, with all parent tables
1487     typedef ::std::vector< const XclBuiltInFormatTable* > XclBuiltInVec;
1488     XclBuiltInVec aBuiltInVec;
1489     for( XclBuiltInMap::const_iterator aMIt = aBuiltInMap.find( meSysLang ), aMEnd = aBuiltInMap.end();
1490             aMIt != aMEnd; aMIt = aBuiltInMap.find( aMIt->second->meParentLang ) )
1491         aBuiltInVec.push_back( aMIt->second );
1492     // language not supported
1493     if( aBuiltInVec.empty() )
1494     {
1495         SAL_WARN("sc",  "XclNumFmtBuffer::InsertBuiltinFormats - language not supported (#i29949#) 0x" << std::hex << meSysLang );
1496         XclBuiltInMap::const_iterator aMIt = aBuiltInMap.find( LANGUAGE_DONTKNOW );
1497         OSL_ENSURE( aMIt != aBuiltInMap.end(), "XclNumFmtBuffer::InsertBuiltinFormats - default map not found" );
1498         if( aMIt != aBuiltInMap.end() )
1499             aBuiltInVec.push_back( aMIt->second );
1500     }
1501 
1502     // insert the default formats in the format map, from root parent to system language
1503     std::map< sal_uInt16, sal_uInt16 > aReuseMap;
1504     for( XclBuiltInVec::reverse_iterator aVIt = aBuiltInVec.rbegin(), aVEnd = aBuiltInVec.rend(); aVIt != aVEnd; ++aVIt )
1505     {
1506         // put LANGUAGE_SYSTEM for all entries in default table
1507         LanguageType eLang = ((*aVIt)->meLanguage == LANGUAGE_DONTKNOW) ? LANGUAGE_SYSTEM : meSysLang;
1508         for( const XclBuiltInFormat* pBuiltIn = (*aVIt)->mpFormats; pBuiltIn && (pBuiltIn->mnXclNumFmt != EXC_FORMAT_NOTFOUND); ++pBuiltIn )
1509         {
1510             XclNumFmt& rNumFmt = maFmtMap[ pBuiltIn->mnXclNumFmt ];
1511 
1512             rNumFmt.meOffset = pBuiltIn->meOffset;
1513             rNumFmt.meLanguage = eLang;
1514 
1515             if( pBuiltIn->mpFormat )
1516                 rNumFmt.maFormat = OUString( pBuiltIn->mpFormat, strlen(pBuiltIn->mpFormat), RTL_TEXTENCODING_UTF8 );
1517             else
1518                 rNumFmt.maFormat = EMPTY_OUSTRING;
1519 
1520             if( pBuiltIn->meOffset == PRV_NF_INDEX_REUSE )
1521                 aReuseMap[ pBuiltIn->mnXclNumFmt ] = pBuiltIn->mnXclReuseFmt;
1522             else
1523                 aReuseMap.erase( pBuiltIn->mnXclNumFmt );
1524         }
1525     }
1526 
1527     // copy reused number formats
1528     for( const auto& [rXclNumFmt, rXclReuseFmt] : aReuseMap )
1529         maFmtMap[ rXclNumFmt ] = maFmtMap[ rXclReuseFmt ];
1530 }
1531 
1532 // Cell formatting data (XF) ==================================================
1533 
XclCellProt()1534 XclCellProt::XclCellProt() :
1535     mbLocked( true ),       // default in Excel and Calc
1536     mbHidden( false )
1537 {
1538 }
1539 
operator ==(const XclCellProt & rLeft,const XclCellProt & rRight)1540 bool operator==( const XclCellProt& rLeft, const XclCellProt& rRight )
1541 {
1542     return (rLeft.mbLocked == rRight.mbLocked) && (rLeft.mbHidden == rRight.mbHidden);
1543 }
1544 
XclCellAlign()1545 XclCellAlign::XclCellAlign() :
1546     mnHorAlign( EXC_XF_HOR_GENERAL ),
1547     mnVerAlign( EXC_XF_VER_BOTTOM ),
1548     mnOrient( EXC_ORIENT_NONE ),
1549     mnTextDir( EXC_XF_TEXTDIR_CONTEXT ),
1550     mnRotation( EXC_ROT_NONE ),
1551     mnIndent( 0 ),
1552     mbLineBreak( false ),
1553     mbShrink( false )
1554 {
1555 }
1556 
GetScHorAlign() const1557 SvxCellHorJustify XclCellAlign::GetScHorAlign() const
1558 {
1559     SvxCellHorJustify eHorJust = SvxCellHorJustify::Standard;
1560     switch( mnHorAlign )
1561     {
1562         case EXC_XF_HOR_GENERAL:    eHorJust = SvxCellHorJustify::Standard;    break;
1563         case EXC_XF_HOR_LEFT:       eHorJust = SvxCellHorJustify::Left;        break;
1564         case EXC_XF_HOR_CENTER_AS:
1565         case EXC_XF_HOR_CENTER:     eHorJust = SvxCellHorJustify::Center;      break;
1566         case EXC_XF_HOR_RIGHT:      eHorJust = SvxCellHorJustify::Right;       break;
1567         case EXC_XF_HOR_FILL:       eHorJust = SvxCellHorJustify::Repeat;      break;
1568         case EXC_XF_HOR_JUSTIFY:
1569         case EXC_XF_HOR_DISTRIB:    eHorJust = SvxCellHorJustify::Block;       break;
1570         default:    OSL_FAIL( "XclCellAlign::GetScHorAlign - unknown horizontal alignment" );
1571     }
1572     return eHorJust;
1573 }
1574 
GetScHorJustifyMethod() const1575 SvxCellJustifyMethod XclCellAlign::GetScHorJustifyMethod() const
1576 {
1577     return (mnHorAlign == EXC_XF_HOR_DISTRIB) ? SvxCellJustifyMethod::Distribute : SvxCellJustifyMethod::Auto;
1578 }
1579 
GetScVerAlign() const1580 SvxCellVerJustify XclCellAlign::GetScVerAlign() const
1581 {
1582     SvxCellVerJustify eVerJust = SvxCellVerJustify::Standard;
1583     switch( mnVerAlign )
1584     {
1585         case EXC_XF_VER_TOP:        eVerJust = SvxCellVerJustify::Top;         break;
1586         case EXC_XF_VER_CENTER:     eVerJust = SvxCellVerJustify::Center;      break;
1587         case EXC_XF_VER_BOTTOM:     eVerJust = SvxCellVerJustify::Standard;    break;
1588         case EXC_XF_VER_JUSTIFY:
1589         case EXC_XF_VER_DISTRIB:    eVerJust = SvxCellVerJustify::Block;       break;
1590         default:    OSL_FAIL( "XclCellAlign::GetScVerAlign - unknown vertical alignment" );
1591     }
1592     return eVerJust;
1593 }
1594 
GetScVerJustifyMethod() const1595 SvxCellJustifyMethod XclCellAlign::GetScVerJustifyMethod() const
1596 {
1597     return (mnVerAlign == EXC_XF_VER_DISTRIB) ? SvxCellJustifyMethod::Distribute : SvxCellJustifyMethod::Auto;
1598 }
1599 
GetScFrameDir() const1600 SvxFrameDirection XclCellAlign::GetScFrameDir() const
1601 {
1602     SvxFrameDirection eFrameDir = SvxFrameDirection::Environment;
1603     switch( mnTextDir )
1604     {
1605         case EXC_XF_TEXTDIR_CONTEXT:    eFrameDir = SvxFrameDirection::Environment;     break;
1606         case EXC_XF_TEXTDIR_LTR:        eFrameDir = SvxFrameDirection::Horizontal_LR_TB;   break;
1607         case EXC_XF_TEXTDIR_RTL:        eFrameDir = SvxFrameDirection::Horizontal_RL_TB;  break;
1608         default:    OSL_FAIL( "XclCellAlign::GetScFrameDir - unknown CTL text direction" );
1609     }
1610     return eFrameDir;
1611 }
1612 
SetScHorAlign(SvxCellHorJustify eHorJust)1613 void XclCellAlign::SetScHorAlign( SvxCellHorJustify eHorJust )
1614 {
1615     switch( eHorJust )
1616     {
1617         case SvxCellHorJustify::Standard:  mnHorAlign = EXC_XF_HOR_GENERAL;    break;
1618         case SvxCellHorJustify::Left:      mnHorAlign = EXC_XF_HOR_LEFT;       break;
1619         case SvxCellHorJustify::Center:    mnHorAlign = EXC_XF_HOR_CENTER;     break;
1620         case SvxCellHorJustify::Right:     mnHorAlign = EXC_XF_HOR_RIGHT;      break;
1621         case SvxCellHorJustify::Block:     mnHorAlign = EXC_XF_HOR_JUSTIFY;    break;
1622         case SvxCellHorJustify::Repeat:    mnHorAlign = EXC_XF_HOR_FILL;       break;
1623         default:                        mnHorAlign = EXC_XF_HOR_GENERAL;
1624             OSL_FAIL( "XclCellAlign::SetScHorAlign - unknown horizontal alignment" );
1625     }
1626 }
1627 
SetScVerAlign(SvxCellVerJustify eVerJust)1628 void XclCellAlign::SetScVerAlign( SvxCellVerJustify eVerJust )
1629 {
1630     switch( eVerJust )
1631     {
1632         case SvxCellVerJustify::Standard:  mnVerAlign = EXC_XF_VER_BOTTOM; break;
1633         case SvxCellVerJustify::Top:       mnVerAlign = EXC_XF_VER_TOP;    break;
1634         case SvxCellVerJustify::Center:    mnVerAlign = EXC_XF_VER_CENTER; break;
1635         case SvxCellVerJustify::Bottom:    mnVerAlign = EXC_XF_VER_BOTTOM; break;
1636         default:                        mnVerAlign = EXC_XF_VER_BOTTOM;
1637             OSL_FAIL( "XclCellAlign::SetScVerAlign - unknown vertical alignment" );
1638     }
1639 }
1640 
SetScFrameDir(SvxFrameDirection eFrameDir)1641 void XclCellAlign::SetScFrameDir( SvxFrameDirection eFrameDir )
1642 {
1643     switch( eFrameDir )
1644     {
1645         case SvxFrameDirection::Environment:      mnTextDir = EXC_XF_TEXTDIR_CONTEXT; break;
1646         case SvxFrameDirection::Horizontal_LR_TB: mnTextDir = EXC_XF_TEXTDIR_LTR;     break;
1647         case SvxFrameDirection::Horizontal_RL_TB: mnTextDir = EXC_XF_TEXTDIR_RTL;     break;
1648         default:                    mnTextDir = EXC_XF_TEXTDIR_CONTEXT;
1649             OSL_FAIL( "XclCellAlign::SetScFrameDir - unknown CTL text direction" );
1650     }
1651 }
1652 
operator ==(const XclCellAlign & rLeft,const XclCellAlign & rRight)1653 bool operator==( const XclCellAlign& rLeft, const XclCellAlign& rRight )
1654 {
1655     return
1656         (rLeft.mnHorAlign  == rRight.mnHorAlign)  && (rLeft.mnVerAlign == rRight.mnVerAlign) &&
1657         (rLeft.mnTextDir   == rRight.mnTextDir)   && (rLeft.mnOrient   == rRight.mnOrient)   &&
1658         (rLeft.mnRotation  == rRight.mnRotation)  && (rLeft.mnIndent   == rRight.mnIndent)   &&
1659         (rLeft.mbLineBreak == rRight.mbLineBreak) && (rLeft.mbShrink   == rRight.mbShrink);
1660 }
1661 
XclCellBorder()1662 XclCellBorder::XclCellBorder() :
1663     mnLeftColor( 0 ),
1664     mnRightColor( 0 ),
1665     mnTopColor( 0 ),
1666     mnBottomColor( 0 ),
1667     mnDiagColor( 0 ),
1668     mnLeftLine( EXC_LINE_NONE ),
1669     mnRightLine( EXC_LINE_NONE ),
1670     mnTopLine( EXC_LINE_NONE ),
1671     mnBottomLine( EXC_LINE_NONE ),
1672     mnDiagLine( EXC_LINE_NONE ),
1673     mbDiagTLtoBR( false ),
1674     mbDiagBLtoTR( false )
1675 {
1676 }
1677 
operator ==(const XclCellBorder & rLeft,const XclCellBorder & rRight)1678 bool operator==( const XclCellBorder& rLeft, const XclCellBorder& rRight )
1679 {
1680     return
1681         (rLeft.mnLeftColor  == rRight.mnLeftColor)  && (rLeft.mnRightColor  == rRight.mnRightColor)  &&
1682         (rLeft.mnTopColor   == rRight.mnTopColor)   && (rLeft.mnBottomColor == rRight.mnBottomColor) &&
1683         (rLeft.mnLeftLine   == rRight.mnLeftLine)   && (rLeft.mnRightLine   == rRight.mnRightLine)   &&
1684         (rLeft.mnTopLine    == rRight.mnTopLine)    && (rLeft.mnBottomLine  == rRight.mnBottomLine)  &&
1685         (rLeft.mnDiagColor  == rRight.mnDiagColor)  && (rLeft.mnDiagLine    == rRight.mnDiagLine)    &&
1686         (rLeft.mbDiagTLtoBR == rRight.mbDiagTLtoBR) && (rLeft.mbDiagBLtoTR  == rRight.mbDiagBLtoTR);
1687 }
1688 
XclCellArea()1689 XclCellArea::XclCellArea() :
1690     mnForeColor( EXC_COLOR_WINDOWTEXT ),
1691     mnBackColor( EXC_COLOR_WINDOWBACK ),
1692     mnPattern( EXC_PATT_NONE )
1693 {
1694 }
1695 
XclCellArea(sal_uInt8 nPattern)1696 XclCellArea::XclCellArea(sal_uInt8 nPattern) :
1697     mnForeColor( EXC_COLOR_WINDOWTEXT ),
1698     mnBackColor( EXC_COLOR_WINDOWBACK ),
1699     mnPattern( nPattern )
1700 {
1701 }
1702 
IsTransparent() const1703 bool XclCellArea::IsTransparent() const
1704 {
1705     return (mnPattern == EXC_PATT_NONE) && (mnBackColor == EXC_COLOR_WINDOWBACK);
1706 }
1707 
operator ==(const XclCellArea & rLeft,const XclCellArea & rRight)1708 bool operator==( const XclCellArea& rLeft, const XclCellArea& rRight )
1709 {
1710     return
1711         (rLeft.mnForeColor == rRight.mnForeColor) && (rLeft.mnBackColor == rRight.mnBackColor) &&
1712         (rLeft.mnPattern == rRight.mnPattern);
1713 }
1714 
XclXFBase(bool bCellXF)1715 XclXFBase::XclXFBase( bool bCellXF ) :
1716     mnParent( bCellXF ? EXC_XF_DEFAULTSTYLE : EXC_XF_STYLEPARENT ),
1717     mbCellXF( bCellXF )
1718 {
1719     SetAllUsedFlags( false );
1720 }
1721 
~XclXFBase()1722 XclXFBase::~XclXFBase()
1723 {
1724 }
1725 
SetAllUsedFlags(bool bUsed)1726 void XclXFBase::SetAllUsedFlags( bool bUsed )
1727 {
1728     mbProtUsed = mbFontUsed = mbFmtUsed = mbAlignUsed = mbBorderUsed = mbAreaUsed = bUsed;
1729 }
1730 
HasUsedFlags() const1731 bool XclXFBase::HasUsedFlags() const
1732 {
1733     return mbProtUsed || mbFontUsed || mbFmtUsed || mbAlignUsed || mbBorderUsed || mbAreaUsed;
1734 }
1735 
Equals(const XclXFBase & rCmp) const1736 bool XclXFBase::Equals( const XclXFBase& rCmp ) const
1737 {
1738     return
1739         (mbCellXF     == rCmp.mbCellXF)     && (mnParent    == rCmp.mnParent)    &&
1740         (mbProtUsed   == rCmp.mbProtUsed)   && (mbFontUsed  == rCmp.mbFontUsed)  &&
1741         (mbFmtUsed    == rCmp.mbFmtUsed)    && (mbAlignUsed == rCmp.mbAlignUsed) &&
1742         (mbBorderUsed == rCmp.mbBorderUsed) && (mbAreaUsed  == rCmp.mbAreaUsed);
1743 }
1744 
1745 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1746