xref: /aoo41x/main/oox/source/xls/stylesbuffer.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include "oox/xls/stylesbuffer.hxx"
29 
30 #include <com/sun/star/awt/FontDescriptor.hpp>
31 #include <com/sun/star/awt/FontFamily.hpp>
32 #include <com/sun/star/awt/FontPitch.hpp>
33 #include <com/sun/star/awt/FontSlant.hpp>
34 #include <com/sun/star/awt/FontStrikeout.hpp>
35 #include <com/sun/star/awt/FontType.hpp>
36 #include <com/sun/star/awt/FontWeight.hpp>
37 #include <com/sun/star/awt/FontUnderline.hpp>
38 #include <com/sun/star/awt/XDevice.hpp>
39 #include <com/sun/star/awt/XFont2.hpp>
40 #include <com/sun/star/container/XIndexAccess.hpp>
41 #include <com/sun/star/container/XNameAccess.hpp>
42 #include <com/sun/star/style/XStyle.hpp>
43 #include <com/sun/star/text/WritingMode2.hpp>
44 #include <com/sun/star/text/XText.hpp>
45 #include <rtl/tencinfo.h>
46 #include <rtl/ustrbuf.hxx>
47 #include "oox/core/filterbase.hxx"
48 #include "oox/helper/attributelist.hxx"
49 #include "oox/helper/containerhelper.hxx"
50 #include "oox/helper/propertymap.hxx"
51 #include "oox/helper/propertyset.hxx"
52 #include "oox/xls/biffinputstream.hxx"
53 #include "oox/xls/condformatbuffer.hxx"
54 #include "oox/xls/excelhandlers.hxx"
55 #include "oox/xls/themebuffer.hxx"
56 #include "oox/xls/unitconverter.hxx"
57 
58 namespace oox {
59 namespace xls {
60 
61 // ============================================================================
62 
63 using namespace ::com::sun::star::awt;
64 using namespace ::com::sun::star::container;
65 using namespace ::com::sun::star::style;
66 using namespace ::com::sun::star::table;
67 using namespace ::com::sun::star::text;
68 using namespace ::com::sun::star::uno;
69 
70 using ::oox::core::FilterBase;
71 using ::rtl::OUString;
72 using ::rtl::OUStringBuffer;
73 
74 // ============================================================================
75 
76 namespace {
77 
78 // OOXML constants ------------------------------------------------------------
79 
80 // OOXML predefined color indexes (also used in BIFF3-BIFF8)
81 const sal_Int32 OOX_COLOR_USEROFFSET        = 0;        /// First user defined color in palette (OOXML/BIFF12).
82 const sal_Int32 BIFF_COLOR_USEROFFSET       = 8;        /// First user defined color in palette (BIFF3-BIFF8).
83 
84 // OOXML font family (also used in BIFF)
85 const sal_Int32 OOX_FONTFAMILY_NONE         = 0;
86 const sal_Int32 OOX_FONTFAMILY_ROMAN        = 1;
87 const sal_Int32 OOX_FONTFAMILY_SWISS        = 2;
88 const sal_Int32 OOX_FONTFAMILY_MODERN       = 3;
89 const sal_Int32 OOX_FONTFAMILY_SCRIPT       = 4;
90 const sal_Int32 OOX_FONTFAMILY_DECORATIVE   = 5;
91 
92 // OOXML cell text direction (also used in BIFF)
93 const sal_Int32 OOX_XF_TEXTDIR_CONTEXT      = 0;
94 const sal_Int32 OOX_XF_TEXTDIR_LTR          = 1;
95 const sal_Int32 OOX_XF_TEXTDIR_RTL          = 2;
96 
97 // OOXML cell rotation (also used in BIFF)
98 const sal_Int32 OOX_XF_ROTATION_NONE        = 0;
99 const sal_Int32 OOX_XF_ROTATION_90CCW       = 90;
100 const sal_Int32 OOX_XF_ROTATION_90CW        = 180;
101 const sal_Int32 OOX_XF_ROTATION_STACKED     = 255;
102 
103 // OOXML cell indentation
104 const sal_Int32 OOX_XF_INDENT_NONE          = 0;
105 
106 // OOXML built-in cell styles (also used in BIFF)
107 const sal_Int32 OOX_STYLE_NORMAL            = 0;        /// Default cell style.
108 const sal_Int32 OOX_STYLE_ROWLEVEL          = 1;        /// RowLevel_x cell style.
109 const sal_Int32 OOX_STYLE_COLLEVEL          = 2;        /// ColLevel_x cell style.
110 
111 const sal_Int32 OOX_STYLE_LEVELCOUNT        = 7;        /// Number of outline level styles.
112 
113 // BIFF12 constants -----------------------------------------------------------
114 
115 // BIFF12 color types
116 const sal_uInt8 BIFF12_COLOR_AUTO           = 0;
117 const sal_uInt8 BIFF12_COLOR_INDEXED        = 1;
118 const sal_uInt8 BIFF12_COLOR_RGB            = 2;
119 const sal_uInt8 BIFF12_COLOR_THEME          = 3;
120 
121 // BIFF12 diagonal borders
122 const sal_uInt8 BIFF12_BORDER_DIAG_TLBR     = 0x01;     /// Top-left to bottom-right.
123 const sal_uInt8 BIFF12_BORDER_DIAG_BLTR     = 0x02;     /// Bottom-left to top-right.
124 
125 // BIFF12 gradient fill
126 const sal_Int32 BIFF12_FILL_GRADIENT        = 40;
127 
128 // BIFF12 XF flags
129 const sal_uInt32 BIFF12_XF_WRAPTEXT         = 0x00400000;
130 const sal_uInt32 BIFF12_XF_JUSTLASTLINE     = 0x00800000;
131 const sal_uInt32 BIFF12_XF_SHRINK           = 0x01000000;
132 const sal_uInt32 BIFF12_XF_LOCKED           = 0x10000000;
133 const sal_uInt32 BIFF12_XF_HIDDEN           = 0x20000000;
134 
135 // BIFF12 XF attribute used flags
136 const sal_uInt16 BIFF12_XF_NUMFMT_USED      = 0x0001;
137 const sal_uInt16 BIFF12_XF_FONT_USED        = 0x0002;
138 const sal_uInt16 BIFF12_XF_ALIGN_USED       = 0x0004;
139 const sal_uInt16 BIFF12_XF_BORDER_USED      = 0x0008;
140 const sal_uInt16 BIFF12_XF_AREA_USED        = 0x0010;
141 const sal_uInt16 BIFF12_XF_PROT_USED        = 0x0020;
142 
143 // BIFF12 DXF constants
144 const sal_uInt16 BIFF12_DXF_FILL_PATTERN    = 0;
145 const sal_uInt16 BIFF12_DXF_FILL_FGCOLOR    = 1;
146 const sal_uInt16 BIFF12_DXF_FILL_BGCOLOR    = 2;
147 const sal_uInt16 BIFF12_DXF_FILL_GRADIENT   = 3;
148 const sal_uInt16 BIFF12_DXF_FILL_STOP       = 4;
149 const sal_uInt16 BIFF12_DXF_FONT_COLOR      = 5;
150 const sal_uInt16 BIFF12_DXF_BORDER_TOP      = 6;
151 const sal_uInt16 BIFF12_DXF_BORDER_BOTTOM   = 7;
152 const sal_uInt16 BIFF12_DXF_BORDER_LEFT     = 8;
153 const sal_uInt16 BIFF12_DXF_BORDER_RIGHT    = 9;
154 const sal_uInt16 BIFF12_DXF_BORDER_DIAG     = 10;
155 const sal_uInt16 BIFF12_DXF_BORDER_VERT     = 11;
156 const sal_uInt16 BIFF12_DXF_BORDER_HOR      = 12;
157 const sal_uInt16 BIFF12_DXF_BORDER_DIAGUP   = 13;
158 const sal_uInt16 BIFF12_DXF_BORDER_DIAGDOWN = 14;
159 const sal_uInt16 BIFF12_DXF_FONT_NAME       = 24;
160 const sal_uInt16 BIFF12_DXF_FONT_WEIGHT     = 25;
161 const sal_uInt16 BIFF12_DXF_FONT_UNDERLINE  = 26;
162 const sal_uInt16 BIFF12_DXF_FONT_ESCAPEMENT = 27;
163 const sal_uInt16 BIFF12_DXF_FONT_ITALIC     = 28;
164 const sal_uInt16 BIFF12_DXF_FONT_STRIKE     = 29;
165 const sal_uInt16 BIFF12_DXF_FONT_OUTLINE    = 30;
166 const sal_uInt16 BIFF12_DXF_FONT_SHADOW     = 31;
167 const sal_uInt16 BIFF12_DXF_FONT_CONDENSE   = 32;
168 const sal_uInt16 BIFF12_DXF_FONT_EXTEND     = 33;
169 const sal_uInt16 BIFF12_DXF_FONT_CHARSET    = 34;
170 const sal_uInt16 BIFF12_DXF_FONT_FAMILY     = 35;
171 const sal_uInt16 BIFF12_DXF_FONT_HEIGHT     = 36;
172 const sal_uInt16 BIFF12_DXF_FONT_SCHEME     = 37;
173 const sal_uInt16 BIFF12_DXF_NUMFMT_CODE     = 38;
174 const sal_uInt16 BIFF12_DXF_NUMFMT_ID       = 41;
175 
176 // BIFF12 CELLSTYLE flags
177 const sal_uInt16 BIFF12_CELLSTYLE_BUILTIN   = 0x0001;
178 const sal_uInt16 BIFF12_CELLSTYLE_HIDDEN    = 0x0002;
179 const sal_uInt16 BIFF12_CELLSTYLE_CUSTOM    = 0x0004;
180 
181 // BIFF constants -------------------------------------------------------------
182 
183 // BIFF predefined color indexes
184 const sal_uInt16 BIFF2_COLOR_BLACK          = 0;        /// Black (text) in BIFF2.
185 const sal_uInt16 BIFF2_COLOR_WHITE          = 1;        /// White (background) in BIFF2.
186 
187 // BIFF font flags, also used in BIFF12
188 const sal_uInt16 BIFF_FONTFLAG_BOLD         = 0x0001;
189 const sal_uInt16 BIFF_FONTFLAG_ITALIC       = 0x0002;
190 const sal_uInt16 BIFF_FONTFLAG_UNDERLINE    = 0x0004;
191 const sal_uInt16 BIFF_FONTFLAG_STRIKEOUT    = 0x0008;
192 const sal_uInt16 BIFF_FONTFLAG_OUTLINE      = 0x0010;
193 const sal_uInt16 BIFF_FONTFLAG_SHADOW       = 0x0020;
194 const sal_uInt16 BIFF_FONTFLAG_CONDENSE     = 0x0040;
195 
196 // BIFF font weight
197 const sal_uInt16 BIFF_FONTWEIGHT_BOLD       = 450;
198 
199 // BIFF font underline, also used in BIFF12
200 const sal_uInt8 BIFF_FONTUNDERL_NONE        = 0;
201 const sal_uInt8 BIFF_FONTUNDERL_SINGLE      = 1;
202 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE      = 2;
203 const sal_uInt8 BIFF_FONTUNDERL_SINGLE_ACC  = 33;
204 const sal_uInt8 BIFF_FONTUNDERL_DOUBLE_ACC  = 34;
205 
206 // BIFF XF flags
207 const sal_uInt16 BIFF_XF_LOCKED             = 0x0001;
208 const sal_uInt16 BIFF_XF_HIDDEN             = 0x0002;
209 const sal_uInt16 BIFF_XF_STYLE              = 0x0004;
210 const sal_uInt16 BIFF_XF_STYLEPARENT        = 0x0FFF;   /// Syles don't have a parent.
211 const sal_uInt16 BIFF_XF_WRAPTEXT           = 0x0008;   /// Automatic line break.
212 const sal_uInt16 BIFF_XF_JUSTLASTLINE       = 0x0080;
213 const sal_uInt16 BIFF_XF_SHRINK             = 0x0010;   /// Shrink to fit into cell.
214 const sal_uInt16 BIFF_XF_MERGE              = 0x0020;
215 
216 // BIFF XF attribute used flags
217 const sal_uInt8 BIFF_XF_NUMFMT_USED         = 0x01;
218 const sal_uInt8 BIFF_XF_FONT_USED           = 0x02;
219 const sal_uInt8 BIFF_XF_ALIGN_USED          = 0x04;
220 const sal_uInt8 BIFF_XF_BORDER_USED         = 0x08;
221 const sal_uInt8 BIFF_XF_AREA_USED           = 0x10;
222 const sal_uInt8 BIFF_XF_PROT_USED           = 0x20;
223 
224 // BIFF XF text orientation
225 const sal_uInt8 BIFF_XF_ORIENT_NONE         = 0;
226 const sal_uInt8 BIFF_XF_ORIENT_STACKED      = 1;        /// Stacked top to bottom.
227 const sal_uInt8 BIFF_XF_ORIENT_90CCW        = 2;        /// 90 degr. counterclockwise.
228 const sal_uInt8 BIFF_XF_ORIENT_90CW         = 3;        /// 90 degr. clockwise.
229 
230 // BIFF XF line styles
231 const sal_uInt8 BIFF_LINE_NONE              = 0;
232 const sal_uInt8 BIFF_LINE_THIN              = 1;
233 
234 // BIFF XF patterns
235 const sal_uInt8 BIFF_PATT_NONE              = 0;
236 const sal_uInt8 BIFF_PATT_125               = 17;
237 
238 // BIFF2 XF flags
239 const sal_uInt8 BIFF2_XF_VALFMT_MASK        = 0x3F;
240 const sal_uInt8 BIFF2_XF_LOCKED             = 0x40;
241 const sal_uInt8 BIFF2_XF_HIDDEN             = 0x80;
242 const sal_uInt8 BIFF2_XF_LEFTLINE           = 0x08;
243 const sal_uInt8 BIFF2_XF_RIGHTLINE          = 0x10;
244 const sal_uInt8 BIFF2_XF_TOPLINE            = 0x20;
245 const sal_uInt8 BIFF2_XF_BOTTOMLINE         = 0x40;
246 const sal_uInt8 BIFF2_XF_BACKGROUND         = 0x80;
247 
248 // BIFF8 diagonal borders
249 const sal_uInt32 BIFF_XF_DIAG_TLBR          = 0x40000000;   /// Top-left to bottom-right.
250 const sal_uInt32 BIFF_XF_DIAG_BLTR          = 0x80000000;   /// Bottom-left to top-right.
251 
252 // BIFF STYLE flags
253 const sal_uInt16 BIFF_STYLE_BUILTIN         = 0x8000;
254 const sal_uInt16 BIFF_STYLE_XFMASK          = 0x0FFF;
255 
256 // BIFF STYLEEXT flags
257 const sal_uInt8 BIFF_STYLEEXT_BUILTIN       = 0x01;
258 const sal_uInt8 BIFF_STYLEEXT_HIDDEN        = 0x02;
259 const sal_uInt8 BIFF_STYLEEXT_CUSTOM        = 0x04;
260 
261 // BIFF conditional formatting
262 const sal_uInt32 BIFF_CFRULE_BORDER_LEFT    = 0x00000400;
263 const sal_uInt32 BIFF_CFRULE_BORDER_RIGHT   = 0x00000800;
264 const sal_uInt32 BIFF_CFRULE_BORDER_TOP     = 0x00001000;
265 const sal_uInt32 BIFF_CFRULE_BORDER_BOTTOM  = 0x00002000;
266 const sal_uInt32 BIFF_CFRULE_FILL_PATTERN   = 0x00010000;
267 const sal_uInt32 BIFF_CFRULE_FILL_PATTCOLOR = 0x00020000;
268 const sal_uInt32 BIFF_CFRULE_FILL_FILLCOLOR = 0x00040000;
269 const sal_uInt32 BIFF_CFRULE_FONTBLOCK      = 0x04000000;
270 const sal_uInt32 BIFF_CFRULE_ALIGNBLOCK     = 0x08000000;
271 const sal_uInt32 BIFF_CFRULE_BORDERBLOCK    = 0x10000000;
272 const sal_uInt32 BIFF_CFRULE_FILLBLOCK      = 0x20000000;
273 const sal_uInt32 BIFF_CFRULE_PROTBLOCK      = 0x40000000;
274 
275 const sal_uInt32 BIFF_CFRULE_FONT_STYLE     = 0x00000002;   /// Font posture or weight modified?
276 const sal_uInt32 BIFF_CFRULE_FONT_OUTLINE   = 0x00000008;   /// Font outline modified?
277 const sal_uInt32 BIFF_CFRULE_FONT_SHADOW    = 0x00000010;   /// Font shadow modified?
278 const sal_uInt32 BIFF_CFRULE_FONT_STRIKEOUT = 0x00000080;   /// Font cancellation modified?
279 const sal_uInt32 BIFF_CFRULE_FONT_UNDERL    = 0x00000001;   /// Font underline type modified?
280 const sal_uInt32 BIFF_CFRULE_FONT_ESCAPEM   = 0x00000001;   /// Font escapement type modified?
281 
282 // ----------------------------------------------------------------------------
283 
284 sal_Int32 lclReadRgbColor( BinaryInputStream& rStrm )
285 {
286     sal_uInt8 nR, nG, nB, nA;
287     rStrm >> nR >> nG >> nB >> nA;
288     sal_Int32 nValue = nA;
289     nValue <<= 8;
290     nValue |= nR;
291     nValue <<= 8;
292     nValue |= nG;
293     nValue <<= 8;
294     nValue |= nB;
295     return nValue;
296 }
297 
298 } // namespace
299 
300 // ============================================================================
301 
302 ExcelGraphicHelper::ExcelGraphicHelper( const WorkbookHelper& rHelper ) :
303     GraphicHelper( rHelper.getBaseFilter().getComponentContext(), rHelper.getBaseFilter().getTargetFrame(), rHelper.getBaseFilter().getStorage() ),
304     WorkbookHelper( rHelper )
305 {
306 }
307 
308 sal_Int32 ExcelGraphicHelper::getSchemeColor( sal_Int32 nToken ) const
309 {
310     if( getFilterType() == FILTER_OOXML )
311         return getTheme().getColorByToken( nToken );
312     return GraphicHelper::getSchemeColor( nToken );
313 }
314 
315 sal_Int32 ExcelGraphicHelper::getPaletteColor( sal_Int32 nPaletteIdx ) const
316 {
317     return getStyles().getPaletteColor( nPaletteIdx );
318 }
319 
320 // ============================================================================
321 
322 void Color::setAuto()
323 {
324     clearTransformations();
325     setSchemeClr( XML_phClr );
326 }
327 
328 void Color::setRgb( sal_Int32 nRgbValue, double fTint )
329 {
330     clearTransformations();
331     setSrgbClr( nRgbValue & 0xFFFFFF );
332     if( fTint != 0.0 ) addExcelTintTransformation( fTint );
333 }
334 
335 void Color::setTheme( sal_Int32 nThemeIdx, double fTint )
336 {
337     clearTransformations();
338     static const sal_Int32 spnColorTokens[] = {
339         XML_lt1, XML_dk1, XML_lt2, XML_dk2, XML_accent1, XML_accent2,
340         XML_accent3, XML_accent4, XML_accent5, XML_accent6, XML_hlink, XML_folHlink };
341     setSchemeClr( STATIC_ARRAY_SELECT( spnColorTokens, nThemeIdx, XML_TOKEN_INVALID ) );
342     if( fTint != 0.0 ) addExcelTintTransformation( fTint );
343 }
344 
345 void Color::setIndexed( sal_Int32 nPaletteIdx, double fTint )
346 {
347     clearTransformations();
348     setPaletteClr( nPaletteIdx );
349     if( fTint != 0.0 ) addExcelTintTransformation( fTint );
350 }
351 
352 void Color::importColor( const AttributeList& rAttribs )
353 {
354     if( rAttribs.getBool( XML_auto, false ) )
355         setAuto();
356     else if( rAttribs.hasAttribute( XML_rgb ) )
357         setRgb( rAttribs.getIntegerHex( XML_rgb, API_RGB_TRANSPARENT ), rAttribs.getDouble( XML_tint, 0.0 ) );
358     else if( rAttribs.hasAttribute( XML_theme ) )
359         setTheme( rAttribs.getInteger( XML_theme, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
360     else if( rAttribs.hasAttribute( XML_indexed ) )
361         setIndexed( rAttribs.getInteger( XML_indexed, -1 ), rAttribs.getDouble( XML_tint, 0.0 ) );
362     else
363     {
364         OSL_ENSURE( false, "Color::importColor - unknown color type" );
365         setAuto();
366     }
367 }
368 
369 void Color::importColor( SequenceInputStream& rStrm )
370 {
371     sal_uInt8 nFlags, nIndex;
372     sal_Int16 nTint;
373     rStrm >> nFlags >> nIndex >> nTint;
374 
375     // scale tint from signed 16-bit to double range -1.0 ... 1.0
376     double fTint = nTint;
377     if( nTint < 0 )
378         fTint /= -SAL_MIN_INT16;
379     else if( nTint > 0 )
380         fTint /= SAL_MAX_INT16;
381 
382     switch( extractValue< sal_uInt8 >( nFlags, 1, 7 ) )
383     {
384         case BIFF12_COLOR_AUTO:
385             setAuto();
386             rStrm.skip( 4 );
387         break;
388         case BIFF12_COLOR_INDEXED:
389             setIndexed( nIndex, fTint );
390             rStrm.skip( 4 );
391         break;
392         case BIFF12_COLOR_RGB:
393             setRgb( lclReadRgbColor( rStrm ), fTint );
394         break;
395         case BIFF12_COLOR_THEME:
396             setTheme( nIndex, fTint );
397             rStrm.skip( 4 );
398         break;
399         default:
400             OSL_ENSURE( false, "Color::importColor - unknown color type" );
401             setAuto();
402             rStrm.skip( 4 );
403     }
404 }
405 
406 void Color::importColorId( SequenceInputStream& rStrm )
407 {
408     setIndexed( rStrm.readInt32() );
409 }
410 
411 void Color::importColorRgb( SequenceInputStream& rStrm )
412 {
413     setRgb( lclReadRgbColor( rStrm ) );
414 }
415 
416 void Color::importColorId( BiffInputStream& rStrm, bool b16Bit )
417 {
418     setIndexed( b16Bit ? rStrm.readuInt16() : rStrm.readuInt8() );
419 }
420 
421 void Color::importColorRgb( BiffInputStream& rStrm )
422 {
423     setRgb( lclReadRgbColor( rStrm ) );
424 }
425 
426 SequenceInputStream& operator>>( SequenceInputStream& rStrm, Color& orColor )
427 {
428     orColor.importColor( rStrm );
429     return rStrm;
430 }
431 
432 // ============================================================================
433 
434 namespace {
435 
436 /** Standard EGA colors, bright. */
437 #define PALETTE_EGA_COLORS_LIGHT \
438             0x000000, 0xFFFFFF, 0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF, 0x00FFFF
439 /** Standard EGA colors, dark. */
440 #define PALETTE_EGA_COLORS_DARK \
441             0x800000, 0x008000, 0x000080, 0x808000, 0x800080, 0x008080, 0xC0C0C0, 0x808080
442 
443 /** Default color table for BIFF2. */
444 static const sal_Int32 spnDefColors2[] =
445 {
446 /*  0 */    PALETTE_EGA_COLORS_LIGHT
447 };
448 
449 /** Default color table for BIFF3/BIFF4. */
450 static const sal_Int32 spnDefColors3[] =
451 {
452 /*  0 */    PALETTE_EGA_COLORS_LIGHT,
453 /*  8 */    PALETTE_EGA_COLORS_LIGHT,
454 /* 16 */    PALETTE_EGA_COLORS_DARK
455 };
456 
457 /** Default color table for BIFF5. */
458 static const sal_Int32 spnDefColors5[] =
459 {
460 /*  0 */    PALETTE_EGA_COLORS_LIGHT,
461 /*  8 */    PALETTE_EGA_COLORS_LIGHT,
462 /* 16 */    PALETTE_EGA_COLORS_DARK,
463 /* 24 */    0x8080FF, 0x802060, 0xFFFFC0, 0xA0E0E0, 0x600080, 0xFF8080, 0x0080C0, 0xC0C0FF,
464 /* 32 */    0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF,
465 /* 40 */    0x00CFFF, 0x69FFFF, 0xE0FFE0, 0xFFFF80, 0xA6CAF0, 0xDD9CB3, 0xB38FEE, 0xE3E3E3,
466 /* 48 */    0x2A6FF9, 0x3FB8CD, 0x488436, 0x958C41, 0x8E5E42, 0xA0627A, 0x624FAC, 0x969696,
467 /* 56 */    0x1D2FBE, 0x286676, 0x004500, 0x453E01, 0x6A2813, 0x85396A, 0x4A3285, 0x424242
468 };
469 
470 /** Default color table for BIFF8/BIFF12/OOXML. */
471 static const sal_Int32 spnDefColors8[] =
472 {
473 /*  0 */    PALETTE_EGA_COLORS_LIGHT,
474 /*  8 */    PALETTE_EGA_COLORS_LIGHT,
475 /* 16 */    PALETTE_EGA_COLORS_DARK,
476 /* 24 */    0x9999FF, 0x993366, 0xFFFFCC, 0xCCFFFF, 0x660066, 0xFF8080, 0x0066CC, 0xCCCCFF,
477 /* 32 */    0x000080, 0xFF00FF, 0xFFFF00, 0x00FFFF, 0x800080, 0x800000, 0x008080, 0x0000FF,
478 /* 40 */    0x00CCFF, 0xCCFFFF, 0xCCFFCC, 0xFFFF99, 0x99CCFF, 0xFF99CC, 0xCC99FF, 0xFFCC99,
479 /* 48 */    0x3366FF, 0x33CCCC, 0x99CC00, 0xFFCC00, 0xFF9900, 0xFF6600, 0x666699, 0x969696,
480 /* 56 */    0x003366, 0x339966, 0x003300, 0x333300, 0x993300, 0x993366, 0x333399, 0x333333
481 };
482 
483 #undef PALETTE_EGA_COLORS_LIGHT
484 #undef PALETTE_EGA_COLORS_DARK
485 
486 } // namespace
487 
488 // ----------------------------------------------------------------------------
489 
490 ColorPalette::ColorPalette( const WorkbookHelper& rHelper ) :
491     WorkbookHelper( rHelper )
492 {
493     // default colors
494     switch( getFilterType() )
495     {
496         case FILTER_OOXML:
497             maColors.insert( maColors.begin(), spnDefColors8, STATIC_ARRAY_END( spnDefColors8 ) );
498             mnAppendIndex = OOX_COLOR_USEROFFSET;
499         break;
500         case FILTER_BIFF:
501             switch( getBiff() )
502             {
503                 case BIFF2: maColors.insert( maColors.begin(), spnDefColors2, STATIC_ARRAY_END( spnDefColors2 ) );  break;
504                 case BIFF3:
505                 case BIFF4: maColors.insert( maColors.begin(), spnDefColors3, STATIC_ARRAY_END( spnDefColors3 ) );  break;
506                 case BIFF5: maColors.insert( maColors.begin(), spnDefColors5, STATIC_ARRAY_END( spnDefColors5 ) );  break;
507                 case BIFF8: maColors.insert( maColors.begin(), spnDefColors8, STATIC_ARRAY_END( spnDefColors8 ) );  break;
508                 case BIFF_UNKNOWN: break;
509             }
510             mnAppendIndex = BIFF_COLOR_USEROFFSET;
511         break;
512         case FILTER_UNKNOWN: break;
513     }
514 }
515 
516 void ColorPalette::importPaletteColor( const AttributeList& rAttribs )
517 {
518     appendColor( rAttribs.getIntegerHex( XML_rgb, API_RGB_WHITE ) );
519 }
520 
521 void ColorPalette::importPaletteColor( SequenceInputStream& rStrm )
522 {
523     sal_Int32 nRgb = lclReadRgbColor( rStrm );
524     appendColor( nRgb & 0xFFFFFF );
525 }
526 
527 void ColorPalette::importPalette( BiffInputStream& rStrm )
528 {
529     sal_uInt16 nCount;
530     rStrm >> nCount;
531     OSL_ENSURE( rStrm.getRemaining() == 4 * nCount, "ColorPalette::importPalette - wrong palette size" );
532 
533     // fill palette from BIFF_COLOR_USEROFFSET
534     mnAppendIndex = BIFF_COLOR_USEROFFSET;
535     for( sal_uInt16 nIndex = 0; !rStrm.isEof() && (nIndex < nCount); ++nIndex )
536     {
537         sal_Int32 nRgb = lclReadRgbColor( rStrm );
538         appendColor( nRgb & 0xFFFFFF );
539     }
540 }
541 
542 void ColorPalette::importPalette( const Any& rPalette )
543 {
544     Sequence< sal_Int32 > rColorSeq;
545     if( (rPalette >>= rColorSeq) && rColorSeq.hasElements() )
546     {
547         const sal_Int32* pnColor = rColorSeq.getConstArray();
548         const sal_Int32* pnColorEnd = pnColor + rColorSeq.getLength();
549         for( ; pnColor < pnColorEnd; ++pnColor )
550             appendColor( *pnColor & 0xFFFFFF );
551     }
552 }
553 
554 sal_Int32 ColorPalette::getColor( sal_Int32 nPaletteIdx ) const
555 {
556     sal_Int32 nColor = API_RGB_TRANSPARENT;
557     if( const sal_Int32* pnPaletteColor = ContainerHelper::getVectorElement( maColors, nPaletteIdx ) )
558     {
559         nColor = *pnPaletteColor;
560     }
561     else switch( nPaletteIdx )
562     {
563         case OOX_COLOR_WINDOWTEXT3:
564         case OOX_COLOR_WINDOWTEXT:
565         case OOX_COLOR_CHWINDOWTEXT:    nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_windowText );   break;
566         case OOX_COLOR_WINDOWBACK3:
567         case OOX_COLOR_WINDOWBACK:
568         case OOX_COLOR_CHWINDOWBACK:    nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_window );       break;
569         case OOX_COLOR_BUTTONBACK:      nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_btnFace );      break;
570         case OOX_COLOR_CHBORDERAUTO:    nColor = API_RGB_BLACK; /* really always black? */                              break;
571         case OOX_COLOR_NOTEBACK:        nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoBk );       break;
572         case OOX_COLOR_NOTETEXT:        nColor = getBaseFilter().getGraphicHelper().getSystemColor( XML_infoText );     break;
573         case OOX_COLOR_FONTAUTO:        nColor = API_RGB_TRANSPARENT;                                                   break;
574         default:                        OSL_ENSURE( false, "ColorPalette::getColor - unknown color index" );
575     }
576     return nColor;
577 }
578 
579 void ColorPalette::appendColor( sal_Int32 nRGBValue )
580 {
581     if( mnAppendIndex < maColors.size() )
582         maColors[ mnAppendIndex ] = nRGBValue;
583     else
584         maColors.push_back( nRGBValue );
585     ++mnAppendIndex;
586 }
587 
588 // ============================================================================
589 
590 namespace {
591 
592 void lclSetFontName( ApiScriptFontName& rFontName, const FontDescriptor& rFontDesc, bool bHasGlyphs )
593 {
594     if( bHasGlyphs )
595     {
596         rFontName.maName = rFontDesc.Name;
597         rFontName.mnFamily = rFontDesc.Family;
598         // API font descriptor contains rtl_TextEncoding constants
599         rFontName.mnTextEnc = rFontDesc.CharSet;
600     }
601     else
602     {
603         rFontName = ApiScriptFontName();
604     }
605 }
606 
607 } // namespace
608 
609 // ----------------------------------------------------------------------------
610 
611 FontModel::FontModel() :
612     mnScheme( XML_none ),
613     mnFamily( OOX_FONTFAMILY_NONE ),
614     mnCharSet( WINDOWS_CHARSET_DEFAULT ),
615     mfHeight( 0.0 ),
616     mnUnderline( XML_none ),
617     mnEscapement( XML_baseline ),
618     mbBold( false ),
619     mbItalic( false ),
620     mbStrikeout( false ),
621     mbOutline( false ),
622     mbShadow( false )
623 {
624 }
625 
626 void FontModel::setBiff12Scheme( sal_uInt8 nScheme )
627 {
628     static const sal_Int32 spnSchemes[] = { XML_none, XML_major, XML_minor };
629     mnScheme = STATIC_ARRAY_SELECT( spnSchemes, nScheme, XML_none );
630 }
631 
632 void FontModel::setBiffHeight( sal_uInt16 nHeight )
633 {
634     mfHeight = nHeight / 20.0;  // convert twips to points
635 }
636 
637 void FontModel::setBiffWeight( sal_uInt16 nWeight )
638 {
639     mbBold = nWeight >= BIFF_FONTWEIGHT_BOLD;
640 }
641 
642 void FontModel::setBiffUnderline( sal_uInt16 nUnderline )
643 {
644     switch( nUnderline )
645     {
646         case BIFF_FONTUNDERL_NONE:          mnUnderline = XML_none;             break;
647         case BIFF_FONTUNDERL_SINGLE:        mnUnderline = XML_single;           break;
648         case BIFF_FONTUNDERL_DOUBLE:        mnUnderline = XML_double;           break;
649         case BIFF_FONTUNDERL_SINGLE_ACC:    mnUnderline = XML_singleAccounting; break;
650         case BIFF_FONTUNDERL_DOUBLE_ACC:    mnUnderline = XML_doubleAccounting; break;
651         default:                            mnUnderline = XML_none;
652     }
653 }
654 
655 void FontModel::setBiffEscapement( sal_uInt16 nEscapement )
656 {
657     static const sal_Int32 spnEscapes[] = { XML_baseline, XML_superscript, XML_subscript };
658     mnEscapement = STATIC_ARRAY_SELECT( spnEscapes, nEscapement, XML_baseline );
659 }
660 
661 // ----------------------------------------------------------------------------
662 
663 ApiFontUsedFlags::ApiFontUsedFlags( bool bAllUsed ) :
664     mbNameUsed( bAllUsed ),
665     mbColorUsed( bAllUsed ),
666     mbSchemeUsed( bAllUsed ),
667     mbHeightUsed( bAllUsed ),
668     mbUnderlineUsed( bAllUsed ),
669     mbEscapementUsed( bAllUsed ),
670     mbWeightUsed( bAllUsed ),
671     mbPostureUsed( bAllUsed ),
672     mbStrikeoutUsed( bAllUsed ),
673     mbOutlineUsed( bAllUsed ),
674     mbShadowUsed( bAllUsed )
675 {
676 }
677 
678 // ----------------------------------------------------------------------------
679 
680 ApiScriptFontName::ApiScriptFontName() :
681     mnFamily( ::com::sun::star::awt::FontFamily::DONTKNOW ),
682     mnTextEnc( RTL_TEXTENCODING_DONTKNOW )
683 {
684 }
685 
686 // ----------------------------------------------------------------------------
687 
688 ApiFontData::ApiFontData() :
689     maDesc(
690         CREATE_OUSTRING( "Calibri" ),
691         220,                                            // height 11 points
692         0,
693         OUString(),
694         ::com::sun::star::awt::FontFamily::DONTKNOW,
695         RTL_TEXTENCODING_DONTKNOW,
696         ::com::sun::star::awt::FontPitch::DONTKNOW,
697         100.0,
698         ::com::sun::star::awt::FontWeight::NORMAL,
699         ::com::sun::star::awt::FontSlant_NONE,
700         ::com::sun::star::awt::FontUnderline::NONE,
701         ::com::sun::star::awt::FontStrikeout::NONE,
702         0.0,
703         sal_False,
704         sal_False,
705         ::com::sun::star::awt::FontType::DONTKNOW ),
706     mnColor( API_RGB_TRANSPARENT ),
707     mnEscapement( API_ESCAPE_NONE ),
708     mnEscapeHeight( API_ESCAPEHEIGHT_NONE ),
709     mbOutline( false ),
710     mbShadow( false )
711 {
712     maLatinFont.maName = maDesc.Name;
713 }
714 
715 // ============================================================================
716 
717 Font::Font( const WorkbookHelper& rHelper, bool bDxf ) :
718     WorkbookHelper( rHelper ),
719     maModel( rHelper.getTheme().getDefaultFontModel() ),
720     maUsedFlags( !bDxf ),
721     mbDxf( bDxf )
722 {
723 }
724 
725 Font::Font( const WorkbookHelper& rHelper, const FontModel& rModel ) :
726     WorkbookHelper( rHelper ),
727     maModel( rModel ),
728     maUsedFlags( true ),
729     mbDxf( false )
730 {
731 }
732 
733 void Font::importAttribs( sal_Int32 nElement, const AttributeList& rAttribs )
734 {
735     const FontModel& rDefModel = getTheme().getDefaultFontModel();
736     switch( nElement )
737     {
738         case XLS_TOKEN( name ):     // when in <font> element
739         case XLS_TOKEN( rFont ):    // when in <rPr> element
740             if( rAttribs.hasAttribute( XML_val ) )
741             {
742                 maModel.maName = rAttribs.getXString( XML_val, OUString() );
743                 maUsedFlags.mbNameUsed = true;
744             }
745         break;
746         case XLS_TOKEN( scheme ):
747             maModel.mnScheme = rAttribs.getToken( XML_val, rDefModel.mnScheme );
748         break;
749         case XLS_TOKEN( family ):
750             maModel.mnFamily = rAttribs.getInteger( XML_val, rDefModel.mnFamily );
751         break;
752         case XLS_TOKEN( charset ):
753             maModel.mnCharSet = rAttribs.getInteger( XML_val, rDefModel.mnCharSet );
754         break;
755         case XLS_TOKEN( sz ):
756             maModel.mfHeight = rAttribs.getDouble( XML_val, rDefModel.mfHeight );
757             maUsedFlags.mbHeightUsed = true;
758         break;
759         case XLS_TOKEN( color ):
760             maModel.maColor.importColor( rAttribs );
761             maUsedFlags.mbColorUsed = true;
762         break;
763         case XLS_TOKEN( u ):
764             maModel.mnUnderline = rAttribs.getToken( XML_val, XML_single );
765             maUsedFlags.mbUnderlineUsed = true;
766         break;
767         case XLS_TOKEN( vertAlign ):
768             maModel.mnEscapement = rAttribs.getToken( XML_val, XML_baseline );
769             maUsedFlags.mbEscapementUsed = true;
770         break;
771         case XLS_TOKEN( b ):
772             maModel.mbBold = rAttribs.getBool( XML_val, true );
773             maUsedFlags.mbWeightUsed = true;
774         break;
775         case XLS_TOKEN( i ):
776             maModel.mbItalic = rAttribs.getBool( XML_val, true );
777             maUsedFlags.mbPostureUsed = true;
778         break;
779         case XLS_TOKEN( strike ):
780             maModel.mbStrikeout = rAttribs.getBool( XML_val, true );
781             maUsedFlags.mbStrikeoutUsed = true;
782         break;
783         case XLS_TOKEN( outline ):
784             maModel.mbOutline = rAttribs.getBool( XML_val, true );
785             maUsedFlags.mbOutlineUsed = true;
786         break;
787         case XLS_TOKEN( shadow ):
788             maModel.mbShadow = rAttribs.getBool( XML_val, true );
789             maUsedFlags.mbShadowUsed = true;
790         break;
791     }
792 }
793 
794 void Font::importFont( SequenceInputStream& rStrm )
795 {
796     OSL_ENSURE( !mbDxf, "Font::importFont - unexpected conditional formatting flag" );
797 
798     sal_uInt16 nHeight, nFlags, nWeight, nEscapement;
799     sal_uInt8 nUnderline, nFamily, nCharSet, nScheme;
800     rStrm >> nHeight >> nFlags >> nWeight >> nEscapement >> nUnderline >> nFamily >> nCharSet;
801     rStrm.skip( 1 );
802     rStrm >> maModel.maColor >> nScheme >> maModel.maName;
803 
804     // equal constants in all BIFFs for weight, underline, and escapement
805     maModel.setBiff12Scheme( nScheme );
806     maModel.setBiffHeight( nHeight );
807     maModel.setBiffWeight( nWeight );
808     maModel.setBiffUnderline( nUnderline );
809     maModel.setBiffEscapement( nEscapement );
810     maModel.mnFamily    = nFamily;
811     maModel.mnCharSet   = nCharSet;
812     // equal flags in all BIFFs
813     maModel.mbItalic    = getFlag( nFlags, BIFF_FONTFLAG_ITALIC );
814     maModel.mbStrikeout = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT );
815     maModel.mbOutline   = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE );
816     maModel.mbShadow    = getFlag( nFlags, BIFF_FONTFLAG_SHADOW );
817 }
818 
819 void Font::importDxfName( SequenceInputStream& rStrm )
820 {
821     OSL_ENSURE( mbDxf, "Font::importDxfName - missing conditional formatting flag" );
822     maModel.maName = BiffHelper::readString( rStrm, false );
823     maUsedFlags.mbColorUsed = true;
824 }
825 
826 void Font::importDxfColor( SequenceInputStream& rStrm )
827 {
828     OSL_ENSURE( mbDxf, "Font::importDxfColor - missing conditional formatting flag" );
829     rStrm >> maModel.maColor;
830     maUsedFlags.mbColorUsed = true;
831 }
832 
833 void Font::importDxfScheme( SequenceInputStream& rStrm )
834 {
835     OSL_ENSURE( mbDxf, "Font::importDxfScheme - missing conditional formatting flag" );
836     maModel.setBiff12Scheme( rStrm.readuInt8() );
837     maUsedFlags.mbSchemeUsed = true;
838 }
839 
840 void Font::importDxfHeight( SequenceInputStream& rStrm )
841 {
842     OSL_ENSURE( mbDxf, "Font::importDxfHeight - missing conditional formatting flag" );
843     maModel.setBiffHeight( rStrm.readuInt16() );
844     maUsedFlags.mbHeightUsed = true;
845 }
846 
847 void Font::importDxfWeight( SequenceInputStream& rStrm )
848 {
849     OSL_ENSURE( mbDxf, "Font::importDxfWeight - missing conditional formatting flag" );
850     maModel.setBiffWeight( rStrm.readuInt16() );
851     maUsedFlags.mbWeightUsed = true;
852 }
853 
854 void Font::importDxfUnderline( SequenceInputStream& rStrm )
855 {
856     OSL_ENSURE( mbDxf, "Font::importDxfUnderline - missing conditional formatting flag" );
857     maModel.setBiffUnderline( rStrm.readuInt16() );
858     maUsedFlags.mbUnderlineUsed = true;
859 }
860 
861 void Font::importDxfEscapement( SequenceInputStream& rStrm )
862 {
863     OSL_ENSURE( mbDxf, "Font::importDxfEscapement - missing conditional formatting flag" );
864     maModel.setBiffEscapement( rStrm.readuInt16() );
865     maUsedFlags.mbEscapementUsed = true;
866 }
867 
868 void Font::importDxfFlag( sal_Int32 nElement, SequenceInputStream& rStrm )
869 {
870     OSL_ENSURE( mbDxf, "Font::importDxfFlag - missing conditional formatting flag" );
871     bool bFlag = rStrm.readuInt8() != 0;
872     switch( nElement )
873     {
874         case XML_i:
875             maModel.mbItalic = bFlag;
876             maUsedFlags.mbPostureUsed = true;
877         break;
878         case XML_strike:
879             maModel.mbStrikeout = bFlag;
880             maUsedFlags.mbStrikeoutUsed = true;
881         break;
882         case XML_outline:
883             maModel.mbOutline = bFlag;
884             maUsedFlags.mbOutlineUsed = true;
885         break;
886         case XML_shadow:
887             maModel.mbShadow = bFlag;
888             maUsedFlags.mbShadowUsed = true;
889         break;
890         default:
891             OSL_ENSURE( false, "Font::importDxfFlag - unexpected element identifier" );
892     }
893 }
894 
895 void Font::importFont( BiffInputStream& rStrm )
896 {
897     OSL_ENSURE( !mbDxf, "Font::importFont - unexpected conditional formatting flag" );
898     switch( getBiff() )
899     {
900         case BIFF2:
901             importFontData2( rStrm );
902             importFontName2( rStrm );
903         break;
904         case BIFF3:
905         case BIFF4:
906             importFontData2( rStrm );
907             importFontColor( rStrm );
908             importFontName2( rStrm );
909         break;
910         case BIFF5:
911             importFontData2( rStrm );
912             importFontColor( rStrm );
913             importFontData5( rStrm );
914             importFontName2( rStrm );
915         break;
916         case BIFF8:
917             importFontData2( rStrm );
918             importFontColor( rStrm );
919             importFontData5( rStrm );
920             importFontName8( rStrm );
921         break;
922         case BIFF_UNKNOWN: break;
923     }
924 }
925 
926 void Font::importFontColor( BiffInputStream& rStrm )
927 {
928     OSL_ENSURE( !mbDxf, "Font::importFontColor - unexpected conditional formatting flag" );
929     maModel.maColor.importColorId( rStrm );
930 }
931 
932 void Font::importCfRule( BiffInputStream& rStrm )
933 {
934     OSL_ENSURE( mbDxf, "Font::importCfRule - missing conditional formatting flag" );
935 
936     sal_Int32 nHeight, nColor;
937     sal_uInt32 nStyle, nFontFlags1, nFontFlags2, nFontFlags3;
938     sal_uInt16 nWeight, nEscapement;
939     sal_uInt8 nUnderline;
940 
941     OSL_ENSURE( rStrm.getRemaining() >= 118, "Font::importCfRule - missing record data" );
942     sal_Int64 nRecPos = rStrm.tell();
943     maModel.maName = rStrm.readUniStringBody( rStrm.readuInt8() );
944     maUsedFlags.mbNameUsed = maModel.maName.getLength() > 0;
945     OSL_ENSURE( !rStrm.isEof() && (rStrm.tell() <= nRecPos + 64), "Font::importCfRule - font name too long" );
946     rStrm.seek( nRecPos + 64 );
947     rStrm >> nHeight >> nStyle >> nWeight >> nEscapement >> nUnderline;
948     rStrm.skip( 3 );
949     rStrm >> nColor;
950     rStrm.skip( 4 );
951     rStrm >> nFontFlags1 >> nFontFlags2 >> nFontFlags3;
952     rStrm.skip( 18 );
953 
954     if( (maUsedFlags.mbColorUsed = (0 <= nColor) && (nColor <= 0x7FFF)) == true )
955         maModel.maColor.setIndexed( nColor );
956     if( (maUsedFlags.mbHeightUsed = (0 < nHeight) && (nHeight <= 0x7FFF)) == true )
957         maModel.setBiffHeight( static_cast< sal_uInt16 >( nHeight ) );
958     if( (maUsedFlags.mbUnderlineUsed = !getFlag( nFontFlags3, BIFF_CFRULE_FONT_UNDERL )) == true )
959         maModel.setBiffUnderline( nUnderline );
960     if( (maUsedFlags.mbEscapementUsed = !getFlag( nFontFlags2, BIFF_CFRULE_FONT_ESCAPEM )) == true )
961         maModel.setBiffEscapement( nEscapement );
962     if( (maUsedFlags.mbWeightUsed = maUsedFlags.mbPostureUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_STYLE )) == true )
963     {
964         maModel.setBiffWeight( nWeight );
965         maModel.mbItalic = getFlag( nStyle, BIFF_CFRULE_FONT_STYLE );
966     }
967     if( (maUsedFlags.mbStrikeoutUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_STRIKEOUT )) == true )
968         maModel.mbStrikeout = getFlag( nStyle, BIFF_CFRULE_FONT_STRIKEOUT );
969     if( (maUsedFlags.mbOutlineUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_OUTLINE )) == true )
970         maModel.mbOutline = getFlag( nStyle, BIFF_CFRULE_FONT_OUTLINE );
971     if( (maUsedFlags.mbShadowUsed = !getFlag( nFontFlags1, BIFF_CFRULE_FONT_SHADOW )) == true )
972         maModel.mbShadow = getFlag( nStyle, BIFF_CFRULE_FONT_SHADOW );
973 }
974 
975 rtl_TextEncoding Font::getFontEncoding() const
976 {
977     // #i63105# cells use text encoding from FONT record character set
978     // #i67768# BIFF2-BIFF4 FONT records do not contain character set
979     // #i71033# do not use maApiData, this function is used before finalizeImport()
980     rtl_TextEncoding eFontEnc = RTL_TEXTENCODING_DONTKNOW;
981     if( (0 <= maModel.mnCharSet) && (maModel.mnCharSet <= SAL_MAX_UINT8) )
982         eFontEnc = rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maModel.mnCharSet ) );
983     return (eFontEnc == RTL_TEXTENCODING_DONTKNOW) ? getTextEncoding() : eFontEnc;
984 }
985 
986 void Font::finalizeImport()
987 {
988     namespace cssawt = ::com::sun::star::awt;
989 
990     // font name
991     maApiData.maDesc.Name = maModel.maName;
992 
993     // font family
994     switch( maModel.mnFamily )
995     {
996         case OOX_FONTFAMILY_NONE:           maApiData.maDesc.Family = cssawt::FontFamily::DONTKNOW;     break;
997         case OOX_FONTFAMILY_ROMAN:          maApiData.maDesc.Family = cssawt::FontFamily::ROMAN;        break;
998         case OOX_FONTFAMILY_SWISS:          maApiData.maDesc.Family = cssawt::FontFamily::SWISS;        break;
999         case OOX_FONTFAMILY_MODERN:         maApiData.maDesc.Family = cssawt::FontFamily::MODERN;       break;
1000         case OOX_FONTFAMILY_SCRIPT:         maApiData.maDesc.Family = cssawt::FontFamily::SCRIPT;       break;
1001         case OOX_FONTFAMILY_DECORATIVE:     maApiData.maDesc.Family = cssawt::FontFamily::DECORATIVE;   break;
1002     }
1003 
1004     // character set (API font descriptor uses rtl_TextEncoding in member CharSet!)
1005     if( (0 <= maModel.mnCharSet) && (maModel.mnCharSet <= SAL_MAX_UINT8) )
1006         maApiData.maDesc.CharSet = static_cast< sal_Int16 >(
1007             rtl_getTextEncodingFromWindowsCharset( static_cast< sal_uInt8 >( maModel.mnCharSet ) ) );
1008 
1009     // color, height, weight, slant, strikeout, outline, shadow
1010     maApiData.mnColor          = maModel.maColor.getColor( getBaseFilter().getGraphicHelper() );
1011     maApiData.maDesc.Height    = static_cast< sal_Int16 >( maModel.mfHeight * 20.0 );
1012     maApiData.maDesc.Weight    = maModel.mbBold ? cssawt::FontWeight::BOLD : cssawt::FontWeight::NORMAL;
1013     maApiData.maDesc.Slant     = maModel.mbItalic ? cssawt::FontSlant_ITALIC : cssawt::FontSlant_NONE;
1014     maApiData.maDesc.Strikeout = maModel.mbStrikeout ? cssawt::FontStrikeout::SINGLE : cssawt::FontStrikeout::NONE;
1015     maApiData.mbOutline        = maModel.mbOutline;
1016     maApiData.mbShadow         = maModel.mbShadow;
1017 
1018     // underline
1019     switch( maModel.mnUnderline )
1020     {
1021         case XML_double:            maApiData.maDesc.Underline = cssawt::FontUnderline::DOUBLE; break;
1022         case XML_doubleAccounting:  maApiData.maDesc.Underline = cssawt::FontUnderline::DOUBLE; break;
1023         case XML_none:              maApiData.maDesc.Underline = cssawt::FontUnderline::NONE;   break;
1024         case XML_single:            maApiData.maDesc.Underline = cssawt::FontUnderline::SINGLE; break;
1025         case XML_singleAccounting:  maApiData.maDesc.Underline = cssawt::FontUnderline::SINGLE; break;
1026     }
1027 
1028     // escapement
1029     switch( maModel.mnEscapement )
1030     {
1031         case XML_baseline:
1032             maApiData.mnEscapement = API_ESCAPE_NONE;
1033             maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_NONE;
1034         break;
1035         case XML_superscript:
1036             maApiData.mnEscapement = API_ESCAPE_SUPERSCRIPT;
1037             maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
1038         break;
1039         case XML_subscript:
1040             maApiData.mnEscapement = API_ESCAPE_SUBSCRIPT;
1041             maApiData.mnEscapeHeight = API_ESCAPEHEIGHT_DEFAULT;
1042         break;
1043     }
1044 
1045     // supported script types
1046     if( maUsedFlags.mbNameUsed )
1047     {
1048         PropertySet aDocProps( getDocument() );
1049         Reference< XDevice > xDevice( aDocProps.getAnyProperty( PROP_ReferenceDevice ), UNO_QUERY );
1050         if( xDevice.is() )
1051         {
1052             Reference< XFont2 > xFont( xDevice->getFont( maApiData.maDesc ), UNO_QUERY );
1053             if( xFont.is() )
1054             {
1055                 // #91658# CJK fonts
1056                 bool bHasAsian =
1057                     xFont->hasGlyphs( OUString( sal_Unicode( 0x3041 ) ) ) ||    // 3040-309F: Hiragana
1058                     xFont->hasGlyphs( OUString( sal_Unicode( 0x30A1 ) ) ) ||    // 30A0-30FF: Katakana
1059                     xFont->hasGlyphs( OUString( sal_Unicode( 0x3111 ) ) ) ||    // 3100-312F: Bopomofo
1060                     xFont->hasGlyphs( OUString( sal_Unicode( 0x3131 ) ) ) ||    // 3130-318F: Hangul Compatibility Jamo
1061                     xFont->hasGlyphs( OUString( sal_Unicode( 0x3301 ) ) ) ||    // 3300-33FF: CJK Compatibility
1062                     xFont->hasGlyphs( OUString( sal_Unicode( 0x3401 ) ) ) ||    // 3400-4DBF: CJK Unified Ideographs Extension A
1063                     xFont->hasGlyphs( OUString( sal_Unicode( 0x4E01 ) ) ) ||    // 4E00-9FAF: CJK Unified Ideographs
1064                     xFont->hasGlyphs( OUString( sal_Unicode( 0x7E01 ) ) ) ||    // 4E00-9FAF: CJK unified ideographs
1065                     xFont->hasGlyphs( OUString( sal_Unicode( 0xA001 ) ) ) ||    // A001-A48F: Yi Syllables
1066                     xFont->hasGlyphs( OUString( sal_Unicode( 0xAC01 ) ) ) ||    // AC00-D7AF: Hangul Syllables
1067                     xFont->hasGlyphs( OUString( sal_Unicode( 0xCC01 ) ) ) ||    // AC00-D7AF: Hangul Syllables
1068                     xFont->hasGlyphs( OUString( sal_Unicode( 0xF901 ) ) ) ||    // F900-FAFF: CJK Compatibility Ideographs
1069                     xFont->hasGlyphs( OUString( sal_Unicode( 0xFF71 ) ) );      // FF00-FFEF: Halfwidth/Fullwidth Forms
1070                 // #113783# CTL fonts
1071                 bool bHasCmplx =
1072                     xFont->hasGlyphs( OUString( sal_Unicode( 0x05D1 ) ) ) ||    // 0590-05FF: Hebrew
1073                     xFont->hasGlyphs( OUString( sal_Unicode( 0x0631 ) ) ) ||    // 0600-06FF: Arabic
1074                     xFont->hasGlyphs( OUString( sal_Unicode( 0x0721 ) ) ) ||    // 0700-074F: Syriac
1075                     xFont->hasGlyphs( OUString( sal_Unicode( 0x0911 ) ) ) ||    // 0900-0DFF: Indic scripts
1076                     xFont->hasGlyphs( OUString( sal_Unicode( 0x0E01 ) ) ) ||    // 0E00-0E7F: Thai
1077                     xFont->hasGlyphs( OUString( sal_Unicode( 0xFB21 ) ) ) ||    // FB1D-FB4F: Hebrew Presentation Forms
1078                     xFont->hasGlyphs( OUString( sal_Unicode( 0xFB51 ) ) ) ||    // FB50-FDFF: Arabic Presentation Forms-A
1079                     xFont->hasGlyphs( OUString( sal_Unicode( 0xFE71 ) ) );      // FE70-FEFF: Arabic Presentation Forms-B
1080                 // Western fonts
1081                 bool bHasLatin =
1082                     (!bHasAsian && !bHasCmplx) ||
1083                     xFont->hasGlyphs( OUString( sal_Unicode( 'A' ) ) );
1084 
1085                 lclSetFontName( maApiData.maLatinFont, maApiData.maDesc, bHasLatin );
1086                 lclSetFontName( maApiData.maAsianFont, maApiData.maDesc, bHasAsian );
1087                 lclSetFontName( maApiData.maCmplxFont, maApiData.maDesc, bHasCmplx );
1088             }
1089         }
1090     }
1091 }
1092 
1093 const FontDescriptor& Font::getFontDescriptor() const
1094 {
1095     return maApiData.maDesc;
1096 }
1097 
1098 bool Font::needsRichTextFormat() const
1099 {
1100     return maApiData.mnEscapement != API_ESCAPE_NONE;
1101 }
1102 
1103 void Font::writeToPropertyMap( PropertyMap& rPropMap, FontPropertyType ePropType ) const
1104 {
1105     // font name properties
1106     if( maUsedFlags.mbNameUsed )
1107     {
1108         if( maApiData.maLatinFont.maName.getLength() > 0 )
1109         {
1110             rPropMap[ PROP_CharFontName ]    <<= maApiData.maLatinFont.maName;
1111             rPropMap[ PROP_CharFontFamily ]  <<= maApiData.maLatinFont.mnFamily;
1112             rPropMap[ PROP_CharFontCharSet ] <<= maApiData.maLatinFont.mnTextEnc;
1113         }
1114         if( maApiData.maAsianFont.maName.getLength() > 0 )
1115         {
1116             rPropMap[ PROP_CharFontNameAsian ]    <<= maApiData.maAsianFont.maName;
1117             rPropMap[ PROP_CharFontFamilyAsian ]  <<= maApiData.maAsianFont.mnFamily;
1118             rPropMap[ PROP_CharFontCharSetAsian ] <<= maApiData.maAsianFont.mnTextEnc;
1119         }
1120         if( maApiData.maCmplxFont.maName.getLength() > 0 )
1121         {
1122             rPropMap[ PROP_CharFontNameComplex ]    <<= maApiData.maCmplxFont.maName;
1123             rPropMap[ PROP_CharFontFamilyComplex ]  <<= maApiData.maCmplxFont.mnFamily;
1124             rPropMap[ PROP_CharFontCharSetComplex ] <<= maApiData.maCmplxFont.mnTextEnc;
1125         }
1126     }
1127     // font height
1128     if( maUsedFlags.mbHeightUsed )
1129     {
1130         float fHeight = static_cast< float >( maApiData.maDesc.Height / 20.0 ); // twips to points
1131         rPropMap[ PROP_CharHeight ] <<= fHeight;
1132         rPropMap[ PROP_CharHeightAsian ] <<= fHeight;
1133         rPropMap[ PROP_CharHeightComplex ] <<= fHeight;
1134     }
1135     // font weight
1136     if( maUsedFlags.mbWeightUsed )
1137     {
1138         float fWeight = maApiData.maDesc.Weight;
1139         rPropMap[ PROP_CharWeight ] <<= fWeight;
1140         rPropMap[ PROP_CharWeightAsian ] <<= fWeight;
1141         rPropMap[ PROP_CharWeightComplex ] <<= fWeight;
1142     }
1143     // font posture
1144     if( maUsedFlags.mbPostureUsed )
1145     {
1146         rPropMap[ PROP_CharPosture ] <<= maApiData.maDesc.Slant;
1147         rPropMap[ PROP_CharPostureAsian ] <<= maApiData.maDesc.Slant;
1148         rPropMap[ PROP_CharPostureComplex ] <<= maApiData.maDesc.Slant;
1149     }
1150     // character color
1151     if( maUsedFlags.mbColorUsed )
1152         rPropMap[ PROP_CharColor ] <<= maApiData.mnColor;
1153     // underline style
1154     if( maUsedFlags.mbUnderlineUsed )
1155         rPropMap[ PROP_CharUnderline ] <<= maApiData.maDesc.Underline;
1156     // strike out style
1157     if( maUsedFlags.mbStrikeoutUsed )
1158         rPropMap[ PROP_CharStrikeout ] <<= maApiData.maDesc.Strikeout;
1159     // outline style
1160     if( maUsedFlags.mbOutlineUsed )
1161         rPropMap[ PROP_CharContoured ] <<= maApiData.mbOutline;
1162     // shadow style
1163     if( maUsedFlags.mbShadowUsed )
1164         rPropMap[ PROP_CharShadowed ] <<= maApiData.mbShadow;
1165     // escapement
1166     if( maUsedFlags.mbEscapementUsed && (ePropType == FONT_PROPTYPE_TEXT) )
1167     {
1168         rPropMap[ PROP_CharEscapement ] <<= maApiData.mnEscapement;
1169         rPropMap[ PROP_CharEscapementHeight ] <<= maApiData.mnEscapeHeight;
1170     }
1171 }
1172 
1173 void Font::writeToPropertySet( PropertySet& rPropSet, FontPropertyType ePropType ) const
1174 {
1175     PropertyMap aPropMap;
1176     writeToPropertyMap( aPropMap, ePropType );
1177     rPropSet.setProperties( aPropMap );
1178 }
1179 
1180 void Font::importFontData2( BiffInputStream& rStrm )
1181 {
1182     sal_uInt16 nHeight, nFlags;
1183     rStrm >> nHeight >> nFlags;
1184 
1185     maModel.setBiffHeight( nHeight );
1186     maModel.mnFamily     = OOX_FONTFAMILY_NONE;
1187     maModel.mnCharSet    = -1;    // ensure to not use font charset in byte string import
1188     maModel.mnUnderline  = getFlagValue( nFlags, BIFF_FONTFLAG_UNDERLINE, XML_single, XML_none );
1189     maModel.mnEscapement = XML_none;
1190     maModel.mbBold       = getFlag( nFlags, BIFF_FONTFLAG_BOLD );
1191     maModel.mbItalic     = getFlag( nFlags, BIFF_FONTFLAG_ITALIC );
1192     maModel.mbStrikeout  = getFlag( nFlags, BIFF_FONTFLAG_STRIKEOUT );
1193     maModel.mbOutline    = getFlag( nFlags, BIFF_FONTFLAG_OUTLINE );
1194     maModel.mbShadow     = getFlag( nFlags, BIFF_FONTFLAG_SHADOW );
1195 }
1196 
1197 void Font::importFontData5( BiffInputStream& rStrm )
1198 {
1199     sal_uInt16 nWeight, nEscapement;
1200     sal_uInt8 nUnderline, nFamily, nCharSet;
1201     rStrm >> nWeight >> nEscapement >> nUnderline >> nFamily >> nCharSet;
1202     rStrm.skip( 1 );
1203 
1204     maModel.setBiffWeight( nWeight );
1205     maModel.setBiffUnderline( nUnderline );
1206     maModel.setBiffEscapement( nEscapement );
1207     // equal constants in XML and BIFF for family and charset
1208     maModel.mnFamily  = nFamily;
1209     maModel.mnCharSet = nCharSet;
1210 }
1211 
1212 void Font::importFontName2( BiffInputStream& rStrm )
1213 {
1214     maModel.maName = rStrm.readByteStringUC( false, getTextEncoding() );
1215 }
1216 
1217 void Font::importFontName8( BiffInputStream& rStrm )
1218 {
1219     maModel.maName = rStrm.readUniStringBody( rStrm.readuInt8() );
1220 }
1221 
1222 // ============================================================================
1223 
1224 AlignmentModel::AlignmentModel() :
1225     mnHorAlign( XML_general ),
1226     mnVerAlign( XML_bottom ),
1227     mnTextDir( OOX_XF_TEXTDIR_CONTEXT ),
1228     mnRotation( OOX_XF_ROTATION_NONE ),
1229     mnIndent( OOX_XF_INDENT_NONE ),
1230     mbWrapText( false ),
1231     mbShrink( false ),
1232     mbJustLastLine( false )
1233 {
1234 }
1235 
1236 void AlignmentModel::setBiffHorAlign( sal_uInt8 nHorAlign )
1237 {
1238     static const sal_Int32 spnHorAligns[] = {
1239         XML_general, XML_left, XML_center, XML_right,
1240         XML_fill, XML_justify, XML_centerContinuous, XML_distributed };
1241     mnHorAlign = STATIC_ARRAY_SELECT( spnHorAligns, nHorAlign, XML_general );
1242 }
1243 
1244 void AlignmentModel::setBiffVerAlign( sal_uInt8 nVerAlign )
1245 {
1246     static const sal_Int32 spnVerAligns[] = {
1247         XML_top, XML_center, XML_bottom, XML_justify, XML_distributed };
1248     mnVerAlign = STATIC_ARRAY_SELECT( spnVerAligns, nVerAlign, XML_bottom );
1249 }
1250 
1251 void AlignmentModel::setBiffTextOrient( sal_uInt8 nTextOrient )
1252 {
1253     static const sal_Int32 spnRotations[] = {
1254         OOX_XF_ROTATION_NONE, OOX_XF_ROTATION_STACKED,
1255         OOX_XF_ROTATION_90CCW, OOX_XF_ROTATION_90CW };
1256     mnRotation = STATIC_ARRAY_SELECT( spnRotations, nTextOrient, OOX_XF_ROTATION_NONE );
1257 }
1258 
1259 // ----------------------------------------------------------------------------
1260 
1261 ApiAlignmentData::ApiAlignmentData() :
1262     meHorJustify( ::com::sun::star::table::CellHoriJustify_STANDARD ),
1263     meVerJustify( ::com::sun::star::table::CellVertJustify_STANDARD ),
1264     meOrientation( ::com::sun::star::table::CellOrientation_STANDARD ),
1265     mnRotation( 0 ),
1266     mnWritingMode( ::com::sun::star::text::WritingMode2::PAGE ),
1267     mnIndent( 0 ),
1268     mbWrapText( false ),
1269     mbShrink( false )
1270 {
1271 }
1272 
1273 bool operator==( const ApiAlignmentData& rLeft, const ApiAlignmentData& rRight )
1274 {
1275     return
1276         (rLeft.meHorJustify  == rRight.meHorJustify) &&
1277         (rLeft.meVerJustify  == rRight.meVerJustify) &&
1278         (rLeft.meOrientation == rRight.meOrientation) &&
1279         (rLeft.mnRotation    == rRight.mnRotation) &&
1280         (rLeft.mnWritingMode == rRight.mnWritingMode) &&
1281         (rLeft.mnIndent      == rRight.mnIndent) &&
1282         (rLeft.mbWrapText    == rRight.mbWrapText) &&
1283         (rLeft.mbShrink      == rRight.mbShrink);
1284 }
1285 
1286 // ============================================================================
1287 
1288 Alignment::Alignment( const WorkbookHelper& rHelper ) :
1289     WorkbookHelper( rHelper )
1290 {
1291 }
1292 
1293 void Alignment::importAlignment( const AttributeList& rAttribs )
1294 {
1295     maModel.mnHorAlign     = rAttribs.getToken( XML_horizontal, XML_general );
1296     maModel.mnVerAlign     = rAttribs.getToken( XML_vertical, XML_bottom );
1297     maModel.mnTextDir      = rAttribs.getInteger( XML_readingOrder, OOX_XF_TEXTDIR_CONTEXT );
1298     maModel.mnRotation     = rAttribs.getInteger( XML_textRotation, OOX_XF_ROTATION_NONE );
1299     maModel.mnIndent       = rAttribs.getInteger( XML_indent, OOX_XF_INDENT_NONE );
1300     maModel.mbWrapText     = rAttribs.getBool( XML_wrapText, false );
1301     maModel.mbShrink       = rAttribs.getBool( XML_shrinkToFit, false );
1302     maModel.mbJustLastLine = rAttribs.getBool( XML_justifyLastLine, false );
1303 }
1304 
1305 void Alignment::setBiff12Data( sal_uInt32 nFlags )
1306 {
1307     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nFlags, 16, 3 ) );
1308     maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nFlags, 19, 3 ) );
1309     maModel.mnTextDir      = extractValue< sal_Int32 >( nFlags, 26, 2 );
1310     maModel.mnRotation     = extractValue< sal_Int32 >( nFlags, 0, 8 );
1311     maModel.mnIndent       = extractValue< sal_uInt8 >( nFlags, 8, 8 );
1312     maModel.mbWrapText     = getFlag( nFlags, BIFF12_XF_WRAPTEXT );
1313     maModel.mbShrink       = getFlag( nFlags, BIFF12_XF_SHRINK );
1314     maModel.mbJustLastLine = getFlag( nFlags, BIFF12_XF_JUSTLASTLINE );
1315 }
1316 
1317 void Alignment::setBiff2Data( sal_uInt8 nFlags )
1318 {
1319     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nFlags, 0, 3 ) );
1320 }
1321 
1322 void Alignment::setBiff3Data( sal_uInt16 nAlign )
1323 {
1324     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) );
1325     maModel.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT ); // new in BIFF3
1326 }
1327 
1328 void Alignment::setBiff4Data( sal_uInt16 nAlign )
1329 {
1330     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) );
1331     maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 2 ) ); // new in BIFF4
1332     maModel.setBiffTextOrient( extractValue< sal_uInt8 >( nAlign, 6, 2 ) ); // new in BIFF4
1333     maModel.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT );
1334 }
1335 
1336 void Alignment::setBiff5Data( sal_uInt16 nAlign )
1337 {
1338     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) );
1339     maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 3 ) );
1340     maModel.setBiffTextOrient( extractValue< sal_uInt8 >( nAlign, 8, 2 ) );
1341     maModel.mbWrapText = getFlag( nAlign, BIFF_XF_WRAPTEXT );
1342 }
1343 
1344 void Alignment::setBiff8Data( sal_uInt16 nAlign, sal_uInt16 nMiscAttrib )
1345 {
1346     maModel.setBiffHorAlign( extractValue< sal_uInt8 >( nAlign, 0, 3 ) );
1347     maModel.setBiffVerAlign( extractValue< sal_uInt8 >( nAlign, 4, 3 ) );
1348     maModel.mnTextDir      = extractValue< sal_Int32 >( nMiscAttrib, 6, 2 ); // new in BIFF8
1349     maModel.mnRotation     = extractValue< sal_Int32 >( nAlign, 8, 8 ); // new in BIFF8
1350     maModel.mnIndent       = extractValue< sal_uInt8 >( nMiscAttrib, 0, 4 ); // new in BIFF8
1351     maModel.mbWrapText     = getFlag( nAlign, BIFF_XF_WRAPTEXT );
1352     maModel.mbShrink       = getFlag( nMiscAttrib, BIFF_XF_SHRINK ); // new in BIFF8
1353     maModel.mbJustLastLine = getFlag( nAlign, BIFF_XF_JUSTLASTLINE ); // new in BIFF8(?)
1354 }
1355 
1356 void Alignment::finalizeImport()
1357 {
1358     namespace csstab = ::com::sun::star::table;
1359     namespace csstxt = ::com::sun::star::text;
1360 
1361     // horizontal alignment
1362     switch( maModel.mnHorAlign )
1363     {
1364         case XML_center:            maApiData.meHorJustify = csstab::CellHoriJustify_CENTER;    break;
1365         case XML_centerContinuous:  maApiData.meHorJustify = csstab::CellHoriJustify_CENTER;    break;
1366         case XML_distributed:       maApiData.meHorJustify = csstab::CellHoriJustify_BLOCK;     break;
1367         case XML_fill:              maApiData.meHorJustify = csstab::CellHoriJustify_REPEAT;    break;
1368         case XML_general:           maApiData.meHorJustify = csstab::CellHoriJustify_STANDARD;  break;
1369         case XML_justify:           maApiData.meHorJustify = csstab::CellHoriJustify_BLOCK;     break;
1370         case XML_left:              maApiData.meHorJustify = csstab::CellHoriJustify_LEFT;      break;
1371         case XML_right:             maApiData.meHorJustify = csstab::CellHoriJustify_RIGHT;     break;
1372     }
1373 
1374     // vertical alignment
1375     switch( maModel.mnVerAlign )
1376     {
1377         case XML_bottom:        maApiData.meVerJustify = csstab::CellVertJustify_BOTTOM;    break;
1378         case XML_center:        maApiData.meVerJustify = csstab::CellVertJustify_CENTER;    break;
1379         case XML_distributed:   maApiData.meVerJustify = csstab::CellVertJustify_TOP;       break;
1380         case XML_justify:       maApiData.meVerJustify = csstab::CellVertJustify_TOP;       break;
1381         case XML_top:           maApiData.meVerJustify = csstab::CellVertJustify_TOP;       break;
1382     }
1383 
1384     /*  indentation: expressed as number of blocks of 3 space characters in
1385         OOXML/BIFF12, and as multiple of 10 points in BIFF8. */
1386     sal_Int32 nIndent = 0;
1387     switch( getFilterType() )
1388     {
1389         case FILTER_OOXML:  nIndent = getUnitConverter().scaleToMm100( 3.0 * maModel.mnIndent, UNIT_SPACE );  break;
1390         case FILTER_BIFF:   nIndent = getUnitConverter().scaleToMm100( 10.0 * maModel.mnIndent, UNIT_POINT ); break;
1391         case FILTER_UNKNOWN: break;
1392     }
1393     if( (0 <= nIndent) && (nIndent <= SAL_MAX_INT16) )
1394         maApiData.mnIndent = static_cast< sal_Int16 >( nIndent );
1395 
1396     // complex text direction
1397     switch( maModel.mnTextDir )
1398     {
1399         case OOX_XF_TEXTDIR_CONTEXT:    maApiData.mnWritingMode = csstxt::WritingMode2::PAGE;   break;
1400         case OOX_XF_TEXTDIR_LTR:        maApiData.mnWritingMode = csstxt::WritingMode2::LR_TB;  break;
1401         case OOX_XF_TEXTDIR_RTL:        maApiData.mnWritingMode = csstxt::WritingMode2::RL_TB;  break;
1402     }
1403 
1404     // rotation: 0-90 means 0 to 90 degrees ccw, 91-180 means 1 to 90 degrees cw, 255 means stacked
1405     sal_Int32 nOoxRot = maModel.mnRotation;
1406     maApiData.mnRotation = ((0 <= nOoxRot) && (nOoxRot <= 90)) ?
1407         (100 * nOoxRot) :
1408         (((91 <= nOoxRot) && (nOoxRot <= 180)) ? (100 * (450 - nOoxRot)) : 0);
1409 
1410     // "Orientation" property used for character stacking
1411     maApiData.meOrientation = (nOoxRot == OOX_XF_ROTATION_STACKED) ?
1412         csstab::CellOrientation_STACKED : csstab::CellOrientation_STANDARD;
1413 
1414     // alignment flags (#i84960 automatic line break, if vertically justified/distributed)
1415     maApiData.mbWrapText = maModel.mbWrapText || (maModel.mnVerAlign == XML_distributed) || (maModel.mnVerAlign == XML_justify);
1416     maApiData.mbShrink = maModel.mbShrink;
1417 
1418 }
1419 
1420 void Alignment::writeToPropertyMap( PropertyMap& rPropMap ) const
1421 {
1422     rPropMap[ PROP_HoriJustify ]     <<= maApiData.meHorJustify;
1423     rPropMap[ PROP_VertJustify ]     <<= maApiData.meVerJustify;
1424     rPropMap[ PROP_WritingMode ]     <<= maApiData.mnWritingMode;
1425     rPropMap[ PROP_RotateAngle ]     <<= maApiData.mnRotation;
1426     rPropMap[ PROP_Orientation ]     <<= maApiData.meOrientation;
1427     rPropMap[ PROP_ParaIndent ]      <<= maApiData.mnIndent;
1428     rPropMap[ PROP_IsTextWrapped ]   <<= maApiData.mbWrapText;
1429     rPropMap[ PROP_ShrinkToFit ]     <<= maApiData.mbShrink;
1430 }
1431 
1432 // ============================================================================
1433 
1434 ProtectionModel::ProtectionModel() :
1435     mbLocked( true ),   // default in Excel and Calc
1436     mbHidden( false )
1437 {
1438 }
1439 
1440 // ----------------------------------------------------------------------------
1441 
1442 ApiProtectionData::ApiProtectionData() :
1443     maCellProt( sal_True, sal_False, sal_False, sal_False )
1444 {
1445 }
1446 
1447 bool operator==( const ApiProtectionData& rLeft, const ApiProtectionData& rRight )
1448 {
1449     return
1450         (rLeft.maCellProt.IsLocked        == rRight.maCellProt.IsLocked) &&
1451         (rLeft.maCellProt.IsFormulaHidden == rRight.maCellProt.IsFormulaHidden) &&
1452         (rLeft.maCellProt.IsHidden        == rRight.maCellProt.IsHidden) &&
1453         (rLeft.maCellProt.IsPrintHidden   == rRight.maCellProt.IsPrintHidden);
1454 }
1455 
1456 // ============================================================================
1457 
1458 Protection::Protection( const WorkbookHelper& rHelper ) :
1459     WorkbookHelper( rHelper )
1460 {
1461 }
1462 
1463 void Protection::importProtection( const AttributeList& rAttribs )
1464 {
1465     maModel.mbLocked = rAttribs.getBool( XML_locked, true );
1466     maModel.mbHidden = rAttribs.getBool( XML_hidden, false );
1467 }
1468 
1469 void Protection::setBiff12Data( sal_uInt32 nFlags )
1470 {
1471     maModel.mbLocked = getFlag( nFlags, BIFF12_XF_LOCKED );
1472     maModel.mbHidden = getFlag( nFlags, BIFF12_XF_HIDDEN );
1473 }
1474 
1475 void Protection::setBiff2Data( sal_uInt8 nNumFmt )
1476 {
1477     maModel.mbLocked = getFlag( nNumFmt, BIFF2_XF_LOCKED );
1478     maModel.mbHidden = getFlag( nNumFmt, BIFF2_XF_HIDDEN );
1479 }
1480 
1481 void Protection::setBiff3Data( sal_uInt16 nProt )
1482 {
1483     maModel.mbLocked = getFlag( nProt, BIFF_XF_LOCKED );
1484     maModel.mbHidden = getFlag( nProt, BIFF_XF_HIDDEN );
1485 }
1486 
1487 void Protection::finalizeImport()
1488 {
1489     maApiData.maCellProt.IsLocked = maModel.mbLocked;
1490     maApiData.maCellProt.IsFormulaHidden = maModel.mbHidden;
1491 }
1492 
1493 void Protection::writeToPropertyMap( PropertyMap& rPropMap ) const
1494 {
1495     rPropMap[ PROP_CellProtection ] <<= maApiData.maCellProt;
1496 }
1497 
1498 // ============================================================================
1499 
1500 BorderLineModel::BorderLineModel( bool bDxf ) :
1501     mnStyle( XML_none ),
1502     mbUsed( !bDxf )
1503 {
1504     maColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1505 }
1506 
1507 void BorderLineModel::setBiffStyle( sal_Int32 nLineStyle )
1508 {
1509     static const sal_Int32 spnStyleIds[] = {
1510         XML_none, XML_thin, XML_medium, XML_dashed,
1511         XML_dotted, XML_thick, XML_double, XML_hair,
1512         XML_mediumDashed, XML_dashDot, XML_mediumDashDot, XML_dashDotDot,
1513         XML_mediumDashDotDot, XML_slantDashDot };
1514     mnStyle = STATIC_ARRAY_SELECT( spnStyleIds, nLineStyle, XML_none );
1515 }
1516 
1517 void BorderLineModel::setBiffData( sal_uInt8 nLineStyle, sal_uInt16 nLineColor )
1518 {
1519     maColor.setIndexed( nLineColor );
1520     setBiffStyle( nLineStyle );
1521 }
1522 
1523 // ----------------------------------------------------------------------------
1524 
1525 BorderModel::BorderModel( bool bDxf ) :
1526     maLeft( bDxf ),
1527     maRight( bDxf ),
1528     maTop( bDxf ),
1529     maBottom( bDxf ),
1530     maDiagonal( bDxf ),
1531     mbDiagTLtoBR( false ),
1532     mbDiagBLtoTR( false )
1533 {
1534 }
1535 
1536 // ----------------------------------------------------------------------------
1537 
1538 ApiBorderData::ApiBorderData() :
1539     mbBorderUsed( false ),
1540     mbDiagUsed( false )
1541 {
1542 }
1543 
1544 bool ApiBorderData::hasAnyOuterBorder() const
1545 {
1546     return
1547         (maBorder.IsTopLineValid    && (maBorder.TopLine.OuterLineWidth > 0)) ||
1548         (maBorder.IsBottomLineValid && (maBorder.BottomLine.OuterLineWidth > 0)) ||
1549         (maBorder.IsLeftLineValid   && (maBorder.LeftLine.OuterLineWidth > 0)) ||
1550         (maBorder.IsRightLineValid  && (maBorder.RightLine.OuterLineWidth > 0));
1551 }
1552 
1553 namespace {
1554 
1555 bool operator==( const BorderLine& rLeft, const BorderLine& rRight )
1556 {
1557     return
1558         (rLeft.Color          == rRight.Color) &&
1559         (rLeft.InnerLineWidth == rRight.InnerLineWidth) &&
1560         (rLeft.OuterLineWidth == rRight.OuterLineWidth) &&
1561         (rLeft.LineDistance   == rRight.LineDistance);
1562 }
1563 
1564 bool operator==( const TableBorder& rLeft, const TableBorder& rRight )
1565 {
1566     return
1567         (rLeft.TopLine               == rRight.TopLine) &&
1568         (rLeft.IsTopLineValid        == rRight.IsTopLineValid) &&
1569         (rLeft.BottomLine            == rRight.BottomLine) &&
1570         (rLeft.IsBottomLineValid     == rRight.IsBottomLineValid) &&
1571         (rLeft.LeftLine              == rRight.LeftLine) &&
1572         (rLeft.IsLeftLineValid       == rRight.IsLeftLineValid) &&
1573         (rLeft.RightLine             == rRight.RightLine) &&
1574         (rLeft.IsRightLineValid      == rRight.IsRightLineValid) &&
1575         (rLeft.HorizontalLine        == rRight.HorizontalLine) &&
1576         (rLeft.IsHorizontalLineValid == rRight.IsHorizontalLineValid) &&
1577         (rLeft.VerticalLine          == rRight.VerticalLine) &&
1578         (rLeft.IsVerticalLineValid   == rRight.IsVerticalLineValid) &&
1579         (rLeft.Distance              == rRight.Distance) &&
1580         (rLeft.IsDistanceValid       == rRight.IsDistanceValid);
1581 }
1582 
1583 } // namespace
1584 
1585 bool operator==( const ApiBorderData& rLeft, const ApiBorderData& rRight )
1586 {
1587     return
1588         (rLeft.maBorder     == rRight.maBorder) &&
1589         (rLeft.maTLtoBR     == rRight.maTLtoBR) &&
1590         (rLeft.maBLtoTR     == rRight.maBLtoTR) &&
1591         (rLeft.mbBorderUsed == rRight.mbBorderUsed) &&
1592         (rLeft.mbDiagUsed   == rRight.mbDiagUsed);
1593 }
1594 
1595 // ============================================================================
1596 
1597 namespace {
1598 
1599 inline void lclSetBorderLineWidth( BorderLine& rBorderLine,
1600         sal_Int16 nOuter, sal_Int16 nDist = API_LINE_NONE, sal_Int16 nInner = API_LINE_NONE )
1601 {
1602     rBorderLine.OuterLineWidth = nOuter;
1603     rBorderLine.LineDistance = nDist;
1604     rBorderLine.InnerLineWidth = nInner;
1605 }
1606 
1607 inline sal_Int32 lclGetBorderLineWidth( const BorderLine& rBorderLine )
1608 {
1609     return rBorderLine.OuterLineWidth + rBorderLine.LineDistance + rBorderLine.InnerLineWidth;
1610 }
1611 
1612 const BorderLine* lclGetThickerLine( const BorderLine& rBorderLine1, sal_Bool bValid1, const BorderLine& rBorderLine2, sal_Bool bValid2 )
1613 {
1614     if( bValid1 && bValid2 )
1615         return (lclGetBorderLineWidth( rBorderLine1 ) < lclGetBorderLineWidth( rBorderLine2 )) ? &rBorderLine2 : &rBorderLine1;
1616     if( bValid1 )
1617         return &rBorderLine1;
1618     if( bValid2 )
1619         return &rBorderLine2;
1620     return 0;
1621 }
1622 
1623 } // namespace
1624 
1625 // ----------------------------------------------------------------------------
1626 
1627 Border::Border( const WorkbookHelper& rHelper, bool bDxf ) :
1628     WorkbookHelper( rHelper ),
1629     maModel( bDxf ),
1630     mbDxf( bDxf )
1631 {
1632 }
1633 
1634 void Border::importBorder( const AttributeList& rAttribs )
1635 {
1636     maModel.mbDiagTLtoBR = rAttribs.getBool( XML_diagonalDown, false );
1637     maModel.mbDiagBLtoTR = rAttribs.getBool( XML_diagonalUp, false );
1638 }
1639 
1640 void Border::importStyle( sal_Int32 nElement, const AttributeList& rAttribs )
1641 {
1642     if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1643     {
1644         pBorderLine->mnStyle = rAttribs.getToken( XML_style, XML_none );
1645         pBorderLine->mbUsed = true;
1646     }
1647 }
1648 
1649 void Border::importColor( sal_Int32 nElement, const AttributeList& rAttribs )
1650 {
1651     if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1652         pBorderLine->maColor.importColor( rAttribs );
1653 }
1654 
1655 void Border::importBorder( SequenceInputStream& rStrm )
1656 {
1657     sal_uInt8 nFlags = rStrm.readuInt8();
1658     maModel.mbDiagTLtoBR = getFlag( nFlags, BIFF12_BORDER_DIAG_TLBR );
1659     maModel.mbDiagBLtoTR = getFlag( nFlags, BIFF12_BORDER_DIAG_BLTR );
1660     maModel.maTop.setBiffStyle( rStrm.readuInt16() );
1661     rStrm >> maModel.maTop.maColor;
1662     maModel.maBottom.setBiffStyle( rStrm.readuInt16() );
1663     rStrm >> maModel.maBottom.maColor;
1664     maModel.maLeft.setBiffStyle( rStrm.readuInt16() );
1665     rStrm >> maModel.maLeft.maColor;
1666     maModel.maRight.setBiffStyle( rStrm.readuInt16() );
1667     rStrm >> maModel.maRight.maColor;
1668     maModel.maDiagonal.setBiffStyle( rStrm.readuInt16() );
1669     rStrm >> maModel.maDiagonal.maColor;
1670 }
1671 
1672 void Border::importDxfBorder( sal_Int32 nElement, SequenceInputStream& rStrm )
1673 {
1674     OSL_ENSURE( mbDxf, "Border::importDxfBorder - missing conditional formatting flag" );
1675     if( BorderLineModel* pBorderLine = getBorderLine( nElement ) )
1676     {
1677         sal_uInt16 nStyle;
1678         rStrm >> pBorderLine->maColor >> nStyle;
1679         pBorderLine->setBiffStyle( nStyle );
1680         pBorderLine->mbUsed = true;
1681     }
1682 }
1683 
1684 void Border::setBiff2Data( sal_uInt8 nFlags )
1685 {
1686     OSL_ENSURE( !mbDxf, "Border::setBiff2Data - unexpected conditional formatting flag" );
1687     maModel.maLeft.setBiffData(   getFlagValue( nFlags, BIFF2_XF_LEFTLINE,   BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK );
1688     maModel.maRight.setBiffData(  getFlagValue( nFlags, BIFF2_XF_RIGHTLINE,  BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK );
1689     maModel.maTop.setBiffData(    getFlagValue( nFlags, BIFF2_XF_TOPLINE,    BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK );
1690     maModel.maBottom.setBiffData( getFlagValue( nFlags, BIFF2_XF_BOTTOMLINE, BIFF_LINE_THIN, BIFF_LINE_NONE ), BIFF2_COLOR_BLACK );
1691     maModel.maDiagonal.mbUsed = false;
1692 }
1693 
1694 void Border::setBiff3Data( sal_uInt32 nBorder )
1695 {
1696     OSL_ENSURE( !mbDxf, "Border::setBiff3Data - unexpected conditional formatting flag" );
1697     maModel.maLeft.setBiffData(   extractValue< sal_uInt8 >( nBorder,  8, 3 ), extractValue< sal_uInt16 >( nBorder, 11, 5 ) );
1698     maModel.maRight.setBiffData(  extractValue< sal_uInt8 >( nBorder, 24, 3 ), extractValue< sal_uInt16 >( nBorder, 27, 5 ) );
1699     maModel.maTop.setBiffData(    extractValue< sal_uInt8 >( nBorder,  0, 3 ), extractValue< sal_uInt16 >( nBorder,  3, 5 ) );
1700     maModel.maBottom.setBiffData( extractValue< sal_uInt8 >( nBorder, 16, 3 ), extractValue< sal_uInt16 >( nBorder, 19, 5 ) );
1701     maModel.maDiagonal.mbUsed = false;
1702 }
1703 
1704 void Border::setBiff5Data( sal_uInt32 nBorder, sal_uInt32 nArea )
1705 {
1706     OSL_ENSURE( !mbDxf, "Border::setBiff5Data - unexpected conditional formatting flag" );
1707     maModel.maLeft.setBiffData(   extractValue< sal_uInt8 >( nBorder,  3, 3 ), extractValue< sal_uInt16 >( nBorder, 16, 7 ) );
1708     maModel.maRight.setBiffData(  extractValue< sal_uInt8 >( nBorder,  6, 3 ), extractValue< sal_uInt16 >( nBorder, 23, 7 ) );
1709     maModel.maTop.setBiffData(    extractValue< sal_uInt8 >( nBorder,  0, 3 ), extractValue< sal_uInt16 >( nBorder,  9, 7 ) );
1710     maModel.maBottom.setBiffData( extractValue< sal_uInt8 >( nArea,   22, 3 ), extractValue< sal_uInt16 >( nArea,   25, 7 ) );
1711     maModel.maDiagonal.mbUsed = false;
1712 }
1713 
1714 void Border::setBiff8Data( sal_uInt32 nBorder1, sal_uInt32 nBorder2 )
1715 {
1716     OSL_ENSURE( !mbDxf, "Border::setBiff8Data - unexpected conditional formatting flag" );
1717     maModel.maLeft.setBiffData(   extractValue< sal_uInt8 >( nBorder1,  0, 4 ), extractValue< sal_uInt16 >( nBorder1, 16, 7 ) );
1718     maModel.maRight.setBiffData(  extractValue< sal_uInt8 >( nBorder1,  4, 4 ), extractValue< sal_uInt16 >( nBorder1, 23, 7 ) );
1719     maModel.maTop.setBiffData(    extractValue< sal_uInt8 >( nBorder1,  8, 4 ), extractValue< sal_uInt16 >( nBorder2,  0, 7 ) );
1720     maModel.maBottom.setBiffData( extractValue< sal_uInt8 >( nBorder1, 12, 4 ), extractValue< sal_uInt16 >( nBorder2,  7, 7 ) );
1721     maModel.mbDiagTLtoBR = getFlag( nBorder1, BIFF_XF_DIAG_TLBR );
1722     maModel.mbDiagBLtoTR = getFlag( nBorder1, BIFF_XF_DIAG_BLTR );
1723     if( maModel.mbDiagTLtoBR || maModel.mbDiagBLtoTR )
1724         maModel.maDiagonal.setBiffData( extractValue< sal_uInt8 >( nBorder2, 21, 4 ), extractValue< sal_uInt16 >( nBorder2, 14, 7 ) );
1725 }
1726 
1727 void Border::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags )
1728 {
1729     OSL_ENSURE( mbDxf, "Border::importCfRule - missing conditional formatting flag" );
1730     OSL_ENSURE( getFlag( nFlags, BIFF_CFRULE_BORDERBLOCK ), "Border::importCfRule - missing border block flag" );
1731     sal_uInt16 nStyle;
1732     sal_uInt32 nColor;
1733     rStrm >> nStyle >> nColor;
1734     rStrm.skip( 2 );
1735     maModel.maLeft.setBiffData(   extractValue< sal_uInt8 >( nStyle,  0, 4 ), extractValue< sal_uInt16 >( nColor,  0, 7 ) );
1736     maModel.maRight.setBiffData(  extractValue< sal_uInt8 >( nStyle,  4, 4 ), extractValue< sal_uInt16 >( nColor,  7, 7 ) );
1737     maModel.maTop.setBiffData(    extractValue< sal_uInt8 >( nStyle,  8, 4 ), extractValue< sal_uInt16 >( nColor, 16, 7 ) );
1738     maModel.maBottom.setBiffData( extractValue< sal_uInt8 >( nStyle, 12, 4 ), extractValue< sal_uInt16 >( nColor, 23, 7 ) );
1739     maModel.maLeft.mbUsed   = !getFlag( nFlags, BIFF_CFRULE_BORDER_LEFT );
1740     maModel.maRight.mbUsed  = !getFlag( nFlags, BIFF_CFRULE_BORDER_RIGHT );
1741     maModel.maTop.mbUsed    = !getFlag( nFlags, BIFF_CFRULE_BORDER_TOP );
1742     maModel.maBottom.mbUsed = !getFlag( nFlags, BIFF_CFRULE_BORDER_BOTTOM );
1743 }
1744 
1745 void Border::finalizeImport()
1746 {
1747     maApiData.mbBorderUsed = maModel.maLeft.mbUsed || maModel.maRight.mbUsed || maModel.maTop.mbUsed || maModel.maBottom.mbUsed;
1748     maApiData.mbDiagUsed   = maModel.maDiagonal.mbUsed;
1749 
1750     maApiData.maBorder.IsLeftLineValid   = convertBorderLine( maApiData.maBorder.LeftLine,   maModel.maLeft );
1751     maApiData.maBorder.IsRightLineValid  = convertBorderLine( maApiData.maBorder.RightLine,  maModel.maRight );
1752     maApiData.maBorder.IsTopLineValid    = convertBorderLine( maApiData.maBorder.TopLine,    maModel.maTop );
1753     maApiData.maBorder.IsBottomLineValid = convertBorderLine( maApiData.maBorder.BottomLine, maModel.maBottom );
1754 
1755     if( !mbDxf )
1756     {
1757         maApiData.maBorder.IsVerticalLineValid = maApiData.maBorder.IsLeftLineValid || maApiData.maBorder.IsRightLineValid;
1758         if( const BorderLine* pVertLine = lclGetThickerLine( maApiData.maBorder.LeftLine, maApiData.maBorder.IsLeftLineValid, maApiData.maBorder.RightLine, maApiData.maBorder.IsRightLineValid ) )
1759             maApiData.maBorder.VerticalLine = *pVertLine;
1760 
1761         maApiData.maBorder.IsHorizontalLineValid = maApiData.maBorder.IsTopLineValid || maApiData.maBorder.IsBottomLineValid;
1762         if( const BorderLine* pHorLine = lclGetThickerLine( maApiData.maBorder.TopLine, maApiData.maBorder.IsTopLineValid, maApiData.maBorder.BottomLine, maApiData.maBorder.IsBottomLineValid ) )
1763             maApiData.maBorder.HorizontalLine = *pHorLine;
1764     }
1765 
1766     if( maModel.mbDiagTLtoBR )
1767         convertBorderLine( maApiData.maTLtoBR, maModel.maDiagonal );
1768     if( maModel.mbDiagBLtoTR )
1769         convertBorderLine( maApiData.maBLtoTR, maModel.maDiagonal );
1770 }
1771 
1772 void Border::writeToPropertyMap( PropertyMap& rPropMap ) const
1773 {
1774     if( maApiData.mbBorderUsed )
1775         rPropMap[ PROP_TableBorder ] <<= maApiData.maBorder;
1776     if( maApiData.mbDiagUsed )
1777     {
1778         rPropMap[ PROP_DiagonalTLBR ] <<= maApiData.maTLtoBR;
1779         rPropMap[ PROP_DiagonalBLTR ] <<= maApiData.maBLtoTR;
1780     }
1781 }
1782 
1783 BorderLineModel* Border::getBorderLine( sal_Int32 nElement )
1784 {
1785     switch( nElement )
1786     {
1787         case XLS_TOKEN( left ):     return &maModel.maLeft;
1788         case XLS_TOKEN( right ):    return &maModel.maRight;
1789         case XLS_TOKEN( top ):      return &maModel.maTop;
1790         case XLS_TOKEN( bottom ):   return &maModel.maBottom;
1791         case XLS_TOKEN( diagonal ): return &maModel.maDiagonal;
1792     }
1793     return 0;
1794 }
1795 
1796 bool Border::convertBorderLine( BorderLine& rBorderLine, const BorderLineModel& rModel )
1797 {
1798     rBorderLine.Color = rModel.maColor.getColor( getBaseFilter().getGraphicHelper(), API_RGB_BLACK );
1799     switch( rModel.mnStyle )
1800     {
1801         case XML_dashDot:           lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );    break;
1802         case XML_dashDotDot:        lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );    break;
1803         case XML_dashed:            lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );    break;
1804         case XML_dotted:            lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );    break;
1805         case XML_double:            lclSetBorderLineWidth( rBorderLine, API_LINE_THIN, API_LINE_THIN, API_LINE_THIN ); break;
1806         case XML_hair:              lclSetBorderLineWidth( rBorderLine, API_LINE_HAIR );    break;
1807         case XML_medium:            lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );  break;
1808         case XML_mediumDashDot:     lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );  break;
1809         case XML_mediumDashDotDot:  lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );  break;
1810         case XML_mediumDashed:      lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );  break;
1811         case XML_none:              lclSetBorderLineWidth( rBorderLine, API_LINE_NONE );    break;
1812         case XML_slantDashDot:      lclSetBorderLineWidth( rBorderLine, API_LINE_MEDIUM );  break;
1813         case XML_thick:             lclSetBorderLineWidth( rBorderLine, API_LINE_THICK );   break;
1814         case XML_thin:              lclSetBorderLineWidth( rBorderLine, API_LINE_THIN );    break;
1815         default:                    lclSetBorderLineWidth( rBorderLine, API_LINE_NONE );    break;
1816     }
1817     return rModel.mbUsed;
1818 }
1819 
1820 
1821 // ============================================================================
1822 
1823 PatternFillModel::PatternFillModel( bool bDxf ) :
1824     mnPattern( XML_none ),
1825     mbPattColorUsed( !bDxf ),
1826     mbFillColorUsed( !bDxf ),
1827     mbPatternUsed( !bDxf )
1828 {
1829     maPatternColor.setIndexed( OOX_COLOR_WINDOWTEXT );
1830     maFillColor.setIndexed( OOX_COLOR_WINDOWBACK );
1831 }
1832 
1833 void PatternFillModel::setBiffPattern( sal_Int32 nPattern )
1834 {
1835     static const sal_Int32 spnPatternIds[] = {
1836         XML_none, XML_solid, XML_mediumGray, XML_darkGray,
1837         XML_lightGray, XML_darkHorizontal, XML_darkVertical, XML_darkDown,
1838         XML_darkUp, XML_darkGrid, XML_darkTrellis, XML_lightHorizontal,
1839         XML_lightVertical, XML_lightDown, XML_lightUp, XML_lightGrid,
1840         XML_lightTrellis, XML_gray125, XML_gray0625 };
1841     mnPattern = STATIC_ARRAY_SELECT( spnPatternIds, nPattern, XML_none );
1842 }
1843 
1844 void PatternFillModel::setBiffData( sal_uInt16 nPatternColor, sal_uInt16 nFillColor, sal_uInt8 nPattern )
1845 {
1846     maPatternColor.setIndexed( nPatternColor );
1847     maFillColor.setIndexed( nFillColor );
1848     // patterns equal in all BIFFs
1849     setBiffPattern( nPattern );
1850 }
1851 
1852 // ----------------------------------------------------------------------------
1853 
1854 GradientFillModel::GradientFillModel() :
1855     mnType( XML_linear ),
1856     mfAngle( 0.0 ),
1857     mfLeft( 0.0 ),
1858     mfRight( 0.0 ),
1859     mfTop( 0.0 ),
1860     mfBottom( 0.0 )
1861 {
1862 }
1863 
1864 void GradientFillModel::readGradient( SequenceInputStream& rStrm )
1865 {
1866     sal_Int32 nType;
1867     rStrm >> nType >> mfAngle >> mfLeft >> mfRight >> mfTop >> mfBottom;
1868     static const sal_Int32 spnTypes[] = { XML_linear, XML_path };
1869     mnType = STATIC_ARRAY_SELECT( spnTypes, nType, XML_TOKEN_INVALID );
1870 }
1871 
1872 void GradientFillModel::readGradientStop( SequenceInputStream& rStrm, bool bDxf )
1873 {
1874     Color aColor;
1875     double fPosition;
1876     if( bDxf )
1877     {
1878         rStrm.skip( 2 );
1879         rStrm >> fPosition >> aColor;
1880     }
1881     else
1882     {
1883         rStrm >> aColor >> fPosition;
1884     }
1885     if( !rStrm.isEof() && (fPosition >= 0.0) )
1886         maColors[ fPosition ] = aColor;
1887 }
1888 
1889 // ----------------------------------------------------------------------------
1890 
1891 ApiSolidFillData::ApiSolidFillData() :
1892     mnColor( API_RGB_TRANSPARENT ),
1893     mbTransparent( true ),
1894     mbUsed( false )
1895 {
1896 }
1897 
1898 bool operator==( const ApiSolidFillData& rLeft, const ApiSolidFillData& rRight )
1899 {
1900     return
1901         (rLeft.mnColor       == rRight.mnColor) &&
1902         (rLeft.mbTransparent == rRight.mbTransparent) &&
1903         (rLeft.mbUsed        == rRight.mbUsed);
1904 }
1905 
1906 // ============================================================================
1907 
1908 namespace {
1909 
1910 inline sal_Int32 lclGetMixedColorComp( sal_Int32 nPatt, sal_Int32 nFill, sal_Int32 nAlpha )
1911 {
1912     return ((nPatt - nFill) * nAlpha) / 0x80 + nFill;
1913 }
1914 
1915 sal_Int32 lclGetMixedColor( sal_Int32 nPattColor, sal_Int32 nFillColor, sal_Int32 nAlpha )
1916 {
1917     return
1918         (lclGetMixedColorComp( nPattColor & 0xFF0000, nFillColor & 0xFF0000, nAlpha ) & 0xFF0000) |
1919         (lclGetMixedColorComp( nPattColor & 0x00FF00, nFillColor & 0x00FF00, nAlpha ) & 0x00FF00) |
1920         (lclGetMixedColorComp( nPattColor & 0x0000FF, nFillColor & 0x0000FF, nAlpha ) & 0x0000FF);
1921 }
1922 
1923 } // namespace
1924 
1925 // ----------------------------------------------------------------------------
1926 
1927 Fill::Fill( const WorkbookHelper& rHelper, bool bDxf ) :
1928     WorkbookHelper( rHelper ),
1929     mbDxf( bDxf )
1930 {
1931 }
1932 
1933 void Fill::importPatternFill( const AttributeList& rAttribs )
1934 {
1935     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1936     mxPatternModel->mnPattern = rAttribs.getToken( XML_patternType, XML_none );
1937     if( mbDxf )
1938         mxPatternModel->mbPatternUsed = rAttribs.hasAttribute( XML_patternType );
1939 }
1940 
1941 void Fill::importFgColor( const AttributeList& rAttribs )
1942 {
1943     OSL_ENSURE( mxPatternModel.get(), "Fill::importFgColor - missing pattern data" );
1944     if( mxPatternModel.get() )
1945     {
1946         mxPatternModel->maPatternColor.importColor( rAttribs );
1947         mxPatternModel->mbPattColorUsed = true;
1948     }
1949 }
1950 
1951 void Fill::importBgColor( const AttributeList& rAttribs )
1952 {
1953     OSL_ENSURE( mxPatternModel.get(), "Fill::importBgColor - missing pattern data" );
1954     if( mxPatternModel.get() )
1955     {
1956         mxPatternModel->maFillColor.importColor( rAttribs );
1957         mxPatternModel->mbFillColorUsed = true;
1958     }
1959 }
1960 
1961 void Fill::importGradientFill( const AttributeList& rAttribs )
1962 {
1963     mxGradientModel.reset( new GradientFillModel );
1964     mxGradientModel->mnType = rAttribs.getToken( XML_type, XML_linear );
1965     mxGradientModel->mfAngle = rAttribs.getDouble( XML_degree, 0.0 );
1966     mxGradientModel->mfLeft = rAttribs.getDouble( XML_left, 0.0 );
1967     mxGradientModel->mfRight = rAttribs.getDouble( XML_right, 0.0 );
1968     mxGradientModel->mfTop = rAttribs.getDouble( XML_top, 0.0 );
1969     mxGradientModel->mfBottom = rAttribs.getDouble( XML_bottom, 0.0 );
1970 }
1971 
1972 void Fill::importColor( const AttributeList& rAttribs, double fPosition )
1973 {
1974     OSL_ENSURE( mxGradientModel.get(), "Fill::importColor - missing gradient data" );
1975     if( mxGradientModel.get() && (fPosition >= 0.0) )
1976         mxGradientModel->maColors[ fPosition ].importColor( rAttribs );
1977 }
1978 
1979 void Fill::importFill( SequenceInputStream& rStrm )
1980 {
1981     OSL_ENSURE( !mbDxf, "Fill::importFill - unexpected conditional formatting flag" );
1982     sal_Int32 nPattern = rStrm.readInt32();
1983     if( nPattern == BIFF12_FILL_GRADIENT )
1984     {
1985         mxGradientModel.reset( new GradientFillModel );
1986         sal_Int32 nStopCount;
1987         rStrm.skip( 16 );
1988         mxGradientModel->readGradient( rStrm );
1989         rStrm >> nStopCount;
1990         for( sal_Int32 nStop = 0; (nStop < nStopCount) && !rStrm.isEof(); ++nStop )
1991             mxGradientModel->readGradientStop( rStrm, false );
1992     }
1993     else
1994     {
1995         mxPatternModel.reset( new PatternFillModel( mbDxf ) );
1996         mxPatternModel->setBiffPattern( nPattern );
1997         rStrm >> mxPatternModel->maPatternColor >> mxPatternModel->maFillColor;
1998     }
1999 }
2000 
2001 void Fill::importDxfPattern( SequenceInputStream& rStrm )
2002 {
2003     OSL_ENSURE( mbDxf, "Fill::importDxfPattern - missing conditional formatting flag" );
2004     if( !mxPatternModel )
2005         mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2006     mxPatternModel->setBiffPattern( rStrm.readuInt8() );
2007     mxPatternModel->mbPatternUsed = true;
2008 }
2009 
2010 void Fill::importDxfFgColor( SequenceInputStream& rStrm )
2011 {
2012     OSL_ENSURE( mbDxf, "Fill::importDxfFgColor - missing conditional formatting flag" );
2013     if( !mxPatternModel )
2014         mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2015     mxPatternModel->maPatternColor.importColor( rStrm );
2016     mxPatternModel->mbPattColorUsed = true;
2017 }
2018 
2019 void Fill::importDxfBgColor( SequenceInputStream& rStrm )
2020 {
2021     OSL_ENSURE( mbDxf, "Fill::importDxfBgColor - missing conditional formatting flag" );
2022     if( !mxPatternModel )
2023         mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2024     mxPatternModel->maFillColor.importColor( rStrm );
2025     mxPatternModel->mbFillColorUsed = true;
2026 }
2027 
2028 void Fill::importDxfGradient( SequenceInputStream& rStrm )
2029 {
2030     OSL_ENSURE( mbDxf, "Fill::importDxfGradient - missing conditional formatting flag" );
2031     if( !mxGradientModel )
2032         mxGradientModel.reset( new GradientFillModel );
2033     mxGradientModel->readGradient( rStrm );
2034 }
2035 
2036 void Fill::importDxfStop( SequenceInputStream& rStrm )
2037 {
2038     OSL_ENSURE( mbDxf, "Fill::importDxfStop - missing conditional formatting flag" );
2039     if( !mxGradientModel )
2040         mxGradientModel.reset( new GradientFillModel );
2041     mxGradientModel->readGradientStop( rStrm, true );
2042 }
2043 
2044 void Fill::setBiff2Data( sal_uInt8 nFlags )
2045 {
2046     OSL_ENSURE( !mbDxf, "Fill::setBiff2Data - unexpected conditional formatting flag" );
2047     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2048     mxPatternModel->setBiffData(
2049         BIFF2_COLOR_BLACK,
2050         BIFF2_COLOR_WHITE,
2051         getFlagValue( nFlags, BIFF2_XF_BACKGROUND, BIFF_PATT_125, BIFF_PATT_NONE ) );
2052 }
2053 
2054 void Fill::setBiff3Data( sal_uInt16 nArea )
2055 {
2056     OSL_ENSURE( !mbDxf, "Fill::setBiff3Data - unexpected conditional formatting flag" );
2057     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2058     mxPatternModel->setBiffData(
2059         extractValue< sal_uInt16 >( nArea, 6, 5 ),
2060         extractValue< sal_uInt16 >( nArea, 11, 5 ),
2061         extractValue< sal_uInt8 >( nArea, 0, 6 ) );
2062 }
2063 
2064 void Fill::setBiff5Data( sal_uInt32 nArea )
2065 {
2066     OSL_ENSURE( !mbDxf, "Fill::setBiff5Data - unexpected conditional formatting flag" );
2067     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2068     mxPatternModel->setBiffData(
2069         extractValue< sal_uInt16 >( nArea, 0, 7 ),
2070         extractValue< sal_uInt16 >( nArea, 7, 7 ),
2071         extractValue< sal_uInt8 >( nArea, 16, 6 ) );
2072 }
2073 
2074 void Fill::setBiff8Data( sal_uInt32 nBorder2, sal_uInt16 nArea )
2075 {
2076     OSL_ENSURE( !mbDxf, "Fill::setBiff8Data - unexpected conditional formatting flag" );
2077     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2078     mxPatternModel->setBiffData(
2079         extractValue< sal_uInt16 >( nArea, 0, 7 ),
2080         extractValue< sal_uInt16 >( nArea, 7, 7 ),
2081         extractValue< sal_uInt8 >( nBorder2, 26, 6 ) );
2082 }
2083 
2084 void Fill::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags )
2085 {
2086     OSL_ENSURE( mbDxf, "Fill::importCfRule - missing conditional formatting flag" );
2087     OSL_ENSURE( getFlag( nFlags, BIFF_CFRULE_FILLBLOCK ), "Fill::importCfRule - missing fill block flag" );
2088     mxPatternModel.reset( new PatternFillModel( mbDxf ) );
2089     sal_uInt32 nFillData;
2090     rStrm >> nFillData;
2091     mxPatternModel->setBiffData(
2092         extractValue< sal_uInt16 >( nFillData, 16, 7 ),
2093         extractValue< sal_uInt16 >( nFillData, 23, 7 ),
2094         extractValue< sal_uInt8 >( nFillData, 10, 6 ) );
2095     mxPatternModel->mbPattColorUsed = !getFlag( nFlags, BIFF_CFRULE_FILL_PATTCOLOR );
2096     mxPatternModel->mbFillColorUsed = !getFlag( nFlags, BIFF_CFRULE_FILL_FILLCOLOR );
2097     mxPatternModel->mbPatternUsed   = !getFlag( nFlags, BIFF_CFRULE_FILL_PATTERN );
2098 }
2099 
2100 void Fill::finalizeImport()
2101 {
2102     const GraphicHelper& rGraphicHelper = getBaseFilter().getGraphicHelper();
2103 
2104     if( mxPatternModel.get() )
2105     {
2106         // finalize the OOXML data struct
2107         PatternFillModel& rModel = *mxPatternModel;
2108         if( mbDxf )
2109         {
2110             if( rModel.mbFillColorUsed && (!rModel.mbPatternUsed || (rModel.mnPattern == XML_solid)) )
2111             {
2112                 rModel.maPatternColor = rModel.maFillColor;
2113                 rModel.mnPattern = XML_solid;
2114                 rModel.mbPattColorUsed = rModel.mbPatternUsed = true;
2115             }
2116             else if( !rModel.mbFillColorUsed && rModel.mbPatternUsed && (rModel.mnPattern == XML_solid) )
2117             {
2118                 rModel.mbPatternUsed = false;
2119             }
2120         }
2121 
2122         // convert to API fill settings
2123         maApiData.mbUsed = rModel.mbPatternUsed;
2124         if( rModel.mnPattern == XML_none )
2125         {
2126             maApiData.mnColor = API_RGB_TRANSPARENT;
2127             maApiData.mbTransparent = true;
2128         }
2129         else
2130         {
2131             sal_Int32 nAlpha = 0x80;
2132             switch( rModel.mnPattern )
2133             {
2134                 case XML_darkDown:          nAlpha = 0x40;  break;
2135                 case XML_darkGray:          nAlpha = 0x60;  break;
2136                 case XML_darkGrid:          nAlpha = 0x40;  break;
2137                 case XML_darkHorizontal:    nAlpha = 0x40;  break;
2138                 case XML_darkTrellis:       nAlpha = 0x60;  break;
2139                 case XML_darkUp:            nAlpha = 0x40;  break;
2140                 case XML_darkVertical:      nAlpha = 0x40;  break;
2141                 case XML_gray0625:          nAlpha = 0x08;  break;
2142                 case XML_gray125:           nAlpha = 0x10;  break;
2143                 case XML_lightDown:         nAlpha = 0x20;  break;
2144                 case XML_lightGray:         nAlpha = 0x20;  break;
2145                 case XML_lightGrid:         nAlpha = 0x38;  break;
2146                 case XML_lightHorizontal:   nAlpha = 0x20;  break;
2147                 case XML_lightTrellis:      nAlpha = 0x30;  break;
2148                 case XML_lightUp:           nAlpha = 0x20;  break;
2149                 case XML_lightVertical:     nAlpha = 0x20;  break;
2150                 case XML_mediumGray:        nAlpha = 0x40;  break;
2151                 case XML_solid:             nAlpha = 0x80;  break;
2152             }
2153 
2154             sal_Int32 nWinTextColor = rGraphicHelper.getSystemColor( XML_windowText );
2155             sal_Int32 nWinColor = rGraphicHelper.getSystemColor( XML_window );
2156 
2157             if( !rModel.mbPattColorUsed )
2158                 rModel.maPatternColor.setAuto();
2159             sal_Int32 nPattColor = rModel.maPatternColor.getColor( rGraphicHelper, nWinTextColor );
2160 
2161             if( !rModel.mbFillColorUsed )
2162                 rModel.maFillColor.setAuto();
2163             sal_Int32 nFillColor = rModel.maFillColor.getColor( rGraphicHelper, nWinColor );
2164 
2165             maApiData.mnColor = lclGetMixedColor( nPattColor, nFillColor, nAlpha );
2166             maApiData.mbTransparent = false;
2167         }
2168     }
2169     else if( mxGradientModel.get() && !mxGradientModel->maColors.empty() )
2170     {
2171         GradientFillModel& rModel = *mxGradientModel;
2172         maApiData.mbUsed = true;    // no support for differential attributes
2173         GradientFillModel::ColorMap::const_iterator aIt = rModel.maColors.begin();
2174         OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
2175         maApiData.mnColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
2176         if( ++aIt != rModel.maColors.end() )
2177         {
2178             OSL_ENSURE( !aIt->second.isAuto(), "Fill::finalizeImport - automatic gradient color" );
2179             sal_Int32 nEndColor = aIt->second.getColor( rGraphicHelper, API_RGB_WHITE );
2180             maApiData.mnColor = lclGetMixedColor( maApiData.mnColor, nEndColor, 0x40 );
2181             maApiData.mbTransparent = false;
2182         }
2183     }
2184 }
2185 
2186 void Fill::writeToPropertyMap( PropertyMap& rPropMap ) const
2187 {
2188     if( maApiData.mbUsed )
2189     {
2190         rPropMap[ PROP_CellBackColor ] <<= maApiData.mnColor;
2191         rPropMap[ PROP_IsCellBackgroundTransparent ] <<= maApiData.mbTransparent;
2192     }
2193 }
2194 
2195 // ============================================================================
2196 
2197 XfModel::XfModel() :
2198     mnStyleXfId( -1 ),
2199     mnFontId( -1 ),
2200     mnNumFmtId( -1 ),
2201     mnBorderId( -1 ),
2202     mnFillId( -1 ),
2203     mbCellXf( true ),
2204     mbFontUsed( false ),
2205     mbNumFmtUsed( false ),
2206     mbAlignUsed( false ),
2207     mbProtUsed( false ),
2208     mbBorderUsed( false ),
2209     mbAreaUsed( false )
2210 {
2211 }
2212 
2213 // ============================================================================
2214 
2215 Xf::Xf( const WorkbookHelper& rHelper ) :
2216     WorkbookHelper( rHelper ),
2217     maAlignment( rHelper ),
2218     maProtection( rHelper ),
2219     meRotationRef( ::com::sun::star::table::CellVertJustify_STANDARD )
2220 {
2221 }
2222 
2223 void Xf::setAllUsedFlags( bool bUsed )
2224 {
2225     maModel.mbAlignUsed = maModel.mbProtUsed = maModel.mbFontUsed =
2226         maModel.mbNumFmtUsed = maModel.mbBorderUsed = maModel.mbAreaUsed = bUsed;
2227 }
2228 
2229 void Xf::importXf( const AttributeList& rAttribs, bool bCellXf )
2230 {
2231     maModel.mbCellXf = bCellXf;
2232     maModel.mnStyleXfId = rAttribs.getInteger( XML_xfId, -1 );
2233     maModel.mnFontId = rAttribs.getInteger( XML_fontId, -1 );
2234     maModel.mnNumFmtId = rAttribs.getInteger( XML_numFmtId, -1 );
2235     maModel.mnBorderId = rAttribs.getInteger( XML_borderId, -1 );
2236     maModel.mnFillId = rAttribs.getInteger( XML_fillId, -1 );
2237 
2238     /*  Default value of the apply*** attributes is dependent on context:
2239         true in cellStyleXfs element, false in cellXfs element... */
2240     maModel.mbAlignUsed  = rAttribs.getBool( XML_applyAlignment,    !maModel.mbCellXf );
2241     maModel.mbProtUsed   = rAttribs.getBool( XML_applyProtection,   !maModel.mbCellXf );
2242     maModel.mbFontUsed   = rAttribs.getBool( XML_applyFont,         !maModel.mbCellXf );
2243     maModel.mbNumFmtUsed = rAttribs.getBool( XML_applyNumberFormat, !maModel.mbCellXf );
2244     maModel.mbBorderUsed = rAttribs.getBool( XML_applyBorder,       !maModel.mbCellXf );
2245     maModel.mbAreaUsed   = rAttribs.getBool( XML_applyFill,         !maModel.mbCellXf );
2246 }
2247 
2248 void Xf::importAlignment( const AttributeList& rAttribs )
2249 {
2250     maAlignment.importAlignment( rAttribs );
2251 }
2252 
2253 void Xf::importProtection( const AttributeList& rAttribs )
2254 {
2255     maProtection.importProtection( rAttribs );
2256 }
2257 
2258 void Xf::importXf( SequenceInputStream& rStrm, bool bCellXf )
2259 {
2260     maModel.mbCellXf = bCellXf;
2261     maModel.mnStyleXfId = rStrm.readuInt16();
2262     maModel.mnNumFmtId = rStrm.readuInt16();
2263     maModel.mnFontId = rStrm.readuInt16();
2264     maModel.mnFillId = rStrm.readuInt16();
2265     maModel.mnBorderId = rStrm.readuInt16();
2266     sal_uInt32 nFlags = rStrm.readuInt32();
2267     maAlignment.setBiff12Data( nFlags );
2268     maProtection.setBiff12Data( nFlags );
2269     // used flags, see comments in Xf::setBiffUsedFlags()
2270     sal_uInt16 nUsedFlags = rStrm.readuInt16();
2271     maModel.mbFontUsed   = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_FONT_USED );
2272     maModel.mbNumFmtUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_NUMFMT_USED );
2273     maModel.mbAlignUsed  = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_ALIGN_USED );
2274     maModel.mbProtUsed   = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_PROT_USED );
2275     maModel.mbBorderUsed = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_BORDER_USED );
2276     maModel.mbAreaUsed   = maModel.mbCellXf == getFlag( nUsedFlags, BIFF12_XF_AREA_USED );
2277 }
2278 
2279 void Xf::importXf( BiffInputStream& rStrm )
2280 {
2281     BorderRef xBorder = getStyles().createBorder( &maModel.mnBorderId );
2282     FillRef xFill = getStyles().createFill( &maModel.mnFillId );
2283 
2284     switch( getBiff() )
2285     {
2286         case BIFF2:
2287         {
2288             sal_uInt8 nFontId, nNumFmtId, nFlags;
2289             rStrm >> nFontId;
2290             rStrm.skip( 1 );
2291             rStrm >> nNumFmtId >> nFlags;
2292 
2293             // only cell XFs in BIFF2, no parent style, used flags always true
2294             setAllUsedFlags( true );
2295 
2296             // attributes
2297             maAlignment.setBiff2Data( nFlags );
2298             maProtection.setBiff2Data( nNumFmtId );
2299             xBorder->setBiff2Data( nFlags );
2300             xFill->setBiff2Data( nFlags );
2301             maModel.mnFontId = static_cast< sal_Int32 >( nFontId );
2302             maModel.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId & BIFF2_XF_VALFMT_MASK );
2303         }
2304         break;
2305 
2306         case BIFF3:
2307         {
2308             sal_uInt32 nBorder;
2309             sal_uInt16 nTypeProt, nAlign, nArea;
2310             sal_uInt8 nFontId, nNumFmtId;
2311             rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder;
2312 
2313             // XF type/parent
2314             maModel.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE ); // new in BIFF3
2315             maModel.mnStyleXfId = extractValue< sal_Int32 >( nAlign, 4, 12 ); // new in BIFF3
2316             // attribute used flags
2317             setBiffUsedFlags( extractValue< sal_uInt8 >( nTypeProt, 10, 6 ) ); // new in BIFF3
2318 
2319             // attributes
2320             maAlignment.setBiff3Data( nAlign );
2321             maProtection.setBiff3Data( nTypeProt );
2322             xBorder->setBiff3Data( nBorder );
2323             xFill->setBiff3Data( nArea );
2324             maModel.mnFontId = static_cast< sal_Int32 >( nFontId );
2325             maModel.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId );
2326         }
2327         break;
2328 
2329         case BIFF4:
2330         {
2331             sal_uInt32 nBorder;
2332             sal_uInt16 nTypeProt, nAlign, nArea;
2333             sal_uInt8 nFontId, nNumFmtId;
2334             rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder;
2335 
2336             // XF type/parent
2337             maModel.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE );
2338             maModel.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 );
2339             // attribute used flags
2340             setBiffUsedFlags( extractValue< sal_uInt8 >( nAlign, 10, 6 ) );
2341 
2342             // attributes
2343             maAlignment.setBiff4Data( nAlign );
2344             maProtection.setBiff3Data( nTypeProt );
2345             xBorder->setBiff3Data( nBorder );
2346             xFill->setBiff3Data( nArea );
2347             maModel.mnFontId = static_cast< sal_Int32 >( nFontId );
2348             maModel.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId );
2349         }
2350         break;
2351 
2352         case BIFF5:
2353         {
2354             sal_uInt32 nArea, nBorder;
2355             sal_uInt16 nFontId, nNumFmtId, nTypeProt, nAlign;
2356             rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nArea >> nBorder;
2357 
2358             // XF type/parent
2359             maModel.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE );
2360             maModel.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 );
2361             // attribute used flags
2362             setBiffUsedFlags( extractValue< sal_uInt8 >( nAlign, 10, 6 ) );
2363 
2364             // attributes
2365             maAlignment.setBiff5Data( nAlign );
2366             maProtection.setBiff3Data( nTypeProt );
2367             xBorder->setBiff5Data( nBorder, nArea );
2368             xFill->setBiff5Data( nArea );
2369             maModel.mnFontId = static_cast< sal_Int32 >( nFontId );
2370             maModel.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId );
2371         }
2372         break;
2373 
2374         case BIFF8:
2375         {
2376             sal_uInt32 nBorder1, nBorder2;
2377             sal_uInt16 nFontId, nNumFmtId, nTypeProt, nAlign, nMiscAttrib, nArea;
2378             rStrm >> nFontId >> nNumFmtId >> nTypeProt >> nAlign >> nMiscAttrib >> nBorder1 >> nBorder2 >> nArea;
2379 
2380             // XF type/parent
2381             maModel.mbCellXf = !getFlag( nTypeProt, BIFF_XF_STYLE );
2382             maModel.mnStyleXfId = extractValue< sal_Int32 >( nTypeProt, 4, 12 );
2383             // attribute used flags
2384             setBiffUsedFlags( extractValue< sal_uInt8 >( nMiscAttrib, 10, 6 ) );
2385 
2386             // attributes
2387             maAlignment.setBiff8Data( nAlign, nMiscAttrib );
2388             maProtection.setBiff3Data( nTypeProt );
2389             xBorder->setBiff8Data( nBorder1, nBorder2 );
2390             xFill->setBiff8Data( nBorder2, nArea );
2391             maModel.mnFontId = static_cast< sal_Int32 >( nFontId );
2392             maModel.mnNumFmtId = static_cast< sal_Int32 >( nNumFmtId );
2393         }
2394         break;
2395 
2396         case BIFF_UNKNOWN: break;
2397     }
2398 }
2399 
2400 void Xf::finalizeImport()
2401 {
2402     StylesBuffer& rStyles = getStyles();
2403 
2404     // alignment and protection
2405     maAlignment.finalizeImport();
2406     maProtection.finalizeImport();
2407 
2408     /*  Enables the used flags, if the formatting attributes differ from the
2409         style XF. In cell XFs Excel uses the cell attributes, if they differ
2410         from the parent style XF (even if the used flag is switched off).
2411         #109899# ...or if the respective flag is not set in parent style XF.
2412      */
2413     const Xf* pStyleXf = isCellXf() ? rStyles.getStyleXf( maModel.mnStyleXfId ).get() : 0;
2414     if( pStyleXf )
2415     {
2416         const XfModel& rStyleData = pStyleXf->maModel;
2417         if( !maModel.mbFontUsed )
2418             maModel.mbFontUsed = !rStyleData.mbFontUsed || (maModel.mnFontId != rStyleData.mnFontId);
2419         if( !maModel.mbNumFmtUsed )
2420             maModel.mbNumFmtUsed = !rStyleData.mbNumFmtUsed || (maModel.mnNumFmtId != rStyleData.mnNumFmtId);
2421         if( !maModel.mbAlignUsed )
2422             maModel.mbAlignUsed = !rStyleData.mbAlignUsed || !(maAlignment.getApiData() == pStyleXf->maAlignment.getApiData());
2423         if( !maModel.mbProtUsed )
2424             maModel.mbProtUsed = !rStyleData.mbProtUsed || !(maProtection.getApiData() == pStyleXf->maProtection.getApiData());
2425         if( !maModel.mbBorderUsed )
2426             maModel.mbBorderUsed = !rStyleData.mbBorderUsed || !rStyles.equalBorders( maModel.mnBorderId, rStyleData.mnBorderId );
2427         if( !maModel.mbAreaUsed )
2428             maModel.mbAreaUsed = !rStyleData.mbAreaUsed || !rStyles.equalFills( maModel.mnFillId, rStyleData.mnFillId );
2429     }
2430 
2431     /*  #i38709# Decide which rotation reference mode to use. If any outer
2432         border line of the cell is set (either explicitly or via cell style),
2433         and the cell contents are rotated, set rotation reference to bottom of
2434         cell. This causes the borders to be painted rotated with the text. */
2435     if( const Alignment* pAlignment = maModel.mbAlignUsed ? &maAlignment : (pStyleXf ? &pStyleXf->maAlignment : 0) )
2436     {
2437         sal_Int32 nBorderId = maModel.mbBorderUsed ? maModel.mnBorderId : (pStyleXf ? pStyleXf->maModel.mnBorderId : -1);
2438         if( const Border* pBorder = rStyles.getBorder( nBorderId ).get() )
2439             if( (pAlignment->getApiData().mnRotation != 0) && pBorder->getApiData().hasAnyOuterBorder() )
2440                 meRotationRef = ::com::sun::star::table::CellVertJustify_BOTTOM;
2441     }
2442 }
2443 
2444 FontRef Xf::getFont() const
2445 {
2446     return getStyles().getFont( maModel.mnFontId );
2447 }
2448 
2449 bool Xf::hasAnyUsedFlags() const
2450 {
2451     return
2452         maModel.mbAlignUsed || maModel.mbProtUsed || maModel.mbFontUsed ||
2453         maModel.mbNumFmtUsed || maModel.mbBorderUsed || maModel.mbAreaUsed;
2454 }
2455 
2456 void Xf::writeToPropertyMap( PropertyMap& rPropMap ) const
2457 {
2458     StylesBuffer& rStyles = getStyles();
2459 
2460     // create and set cell style
2461     if( isCellXf() )
2462         rPropMap[ PROP_CellStyle ] <<= rStyles.createCellStyle( maModel.mnStyleXfId );
2463 
2464     if( maModel.mbFontUsed )
2465         rStyles.writeFontToPropertyMap( rPropMap, maModel.mnFontId );
2466     if( maModel.mbNumFmtUsed )
2467         rStyles.writeNumFmtToPropertyMap( rPropMap, maModel.mnNumFmtId );
2468     if( maModel.mbAlignUsed )
2469         maAlignment.writeToPropertyMap( rPropMap );
2470     if( maModel.mbProtUsed )
2471         maProtection.writeToPropertyMap( rPropMap );
2472     if( maModel.mbBorderUsed )
2473         rStyles.writeBorderToPropertyMap( rPropMap, maModel.mnBorderId );
2474     if( maModel.mbAreaUsed )
2475         rStyles.writeFillToPropertyMap( rPropMap, maModel.mnFillId );
2476     if( maModel.mbAlignUsed || maModel.mbBorderUsed )
2477         rPropMap[ PROP_RotateReference ] <<= meRotationRef;
2478 }
2479 
2480 void Xf::writeToPropertySet( PropertySet& rPropSet ) const
2481 {
2482     PropertyMap aPropMap;
2483     writeToPropertyMap( aPropMap );
2484     rPropSet.setProperties( aPropMap );
2485 }
2486 
2487 /*static*/ void Xf::writeBiff2CellFormatToPropertySet( const WorkbookHelper& rHelper,
2488         PropertySet& rPropSet, sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 )
2489 {
2490     /*  Create an XF object and let it do the work. We will have access to its
2491         private members here. Also, create temporary border and fill objects,
2492         this prevents polluting the border and fill buffers with new temporary
2493         objects per imported cell. */
2494     Xf aXf( rHelper );
2495     Border aBorder( rHelper, false );
2496     Fill aFill( rHelper, false );
2497 
2498     // no used flags available in BIFF2 (always true)
2499     aXf.setAllUsedFlags( true );
2500 
2501     // set the attributes
2502     aXf.maModel.mnFontId = extractValue< sal_Int32 >( nFlags2, 6, 2 );
2503     aXf.maModel.mnNumFmtId = extractValue< sal_Int32 >( nFlags2, 0, 6 );
2504     aXf.maAlignment.setBiff2Data( nFlags3 );
2505     aXf.maProtection.setBiff2Data( nFlags1 );
2506     aBorder.setBiff2Data( nFlags3 );
2507     aFill.setBiff2Data( nFlags3 );
2508 
2509     // finalize the objects (convert model to API attributes)
2510     aXf.finalizeImport();
2511     aBorder.finalizeImport();
2512     aFill.finalizeImport();
2513 
2514     // write the properties to the property set
2515     PropertyMap aPropMap;
2516     aXf.writeToPropertyMap( aPropMap );
2517     aBorder.writeToPropertyMap( aPropMap );
2518     aFill.writeToPropertyMap( aPropMap );
2519     rPropSet.setProperties( aPropMap );
2520 }
2521 
2522 void Xf::setBiffUsedFlags( sal_uInt8 nUsedFlags )
2523 {
2524     /*  Notes about finding the used flags:
2525         - In cell XFs a *set* bit means a used attribute.
2526         - In style XFs a *cleared* bit means a used attribute.
2527         The boolean flags always store true, if the attribute is used.
2528         The "isCellXf() == getFlag(...)" construct evaluates to true in both
2529         mentioned cases: cell XF and set bit; or style XF and cleared bit.
2530      */
2531     maModel.mbFontUsed   = isCellXf() == getFlag( nUsedFlags, BIFF_XF_FONT_USED );
2532     maModel.mbNumFmtUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_NUMFMT_USED );
2533     maModel.mbAlignUsed  = isCellXf() == getFlag( nUsedFlags, BIFF_XF_ALIGN_USED );
2534     maModel.mbProtUsed   = isCellXf() == getFlag( nUsedFlags, BIFF_XF_PROT_USED );
2535     maModel.mbBorderUsed = isCellXf() == getFlag( nUsedFlags, BIFF_XF_BORDER_USED );
2536     maModel.mbAreaUsed   = isCellXf() == getFlag( nUsedFlags, BIFF_XF_AREA_USED );
2537 }
2538 
2539 // ============================================================================
2540 
2541 Dxf::Dxf( const WorkbookHelper& rHelper ) :
2542     WorkbookHelper( rHelper )
2543 {
2544 }
2545 
2546 FontRef Dxf::createFont( bool bAlwaysNew )
2547 {
2548     if( bAlwaysNew || !mxFont )
2549         mxFont.reset( new Font( *this, true ) );
2550     return mxFont;
2551 }
2552 
2553 BorderRef Dxf::createBorder( bool bAlwaysNew )
2554 {
2555     if( bAlwaysNew || !mxBorder )
2556         mxBorder.reset( new Border( *this, true ) );
2557     return mxBorder;
2558 }
2559 
2560 FillRef Dxf::createFill( bool bAlwaysNew )
2561 {
2562     if( bAlwaysNew || !mxFill )
2563         mxFill.reset( new Fill( *this, true ) );
2564     return mxFill;
2565 }
2566 
2567 void Dxf::importNumFmt( const AttributeList& rAttribs )
2568 {
2569     mxNumFmt = getStyles().importNumFmt( rAttribs );
2570 }
2571 
2572 void Dxf::importAlignment( const AttributeList& rAttribs )
2573 {
2574     mxAlignment.reset( new Alignment( *this ) );
2575     mxAlignment->importAlignment( rAttribs );
2576 }
2577 
2578 void Dxf::importProtection( const AttributeList& rAttribs )
2579 {
2580     mxProtection.reset( new Protection( *this ) );
2581     mxProtection->importProtection( rAttribs );
2582 }
2583 
2584 void Dxf::importDxf( SequenceInputStream& rStrm )
2585 {
2586     sal_Int32 nNumFmtId = -1;
2587     OUString aFmtCode;
2588     sal_uInt16 nRecCount;
2589     rStrm.skip( 4 );    // flags
2590     rStrm >> nRecCount;
2591     for( sal_uInt16 nRec = 0; !rStrm.isEof() && (nRec < nRecCount); ++nRec )
2592     {
2593         sal_uInt16 nSubRecId, nSubRecSize;
2594         sal_Int64 nRecEnd = rStrm.tell();
2595         rStrm >> nSubRecId >> nSubRecSize;
2596         nRecEnd += nSubRecSize;
2597         switch( nSubRecId )
2598         {
2599             case BIFF12_DXF_FILL_PATTERN:       createFill( false )->importDxfPattern( rStrm );                         break;
2600             case BIFF12_DXF_FILL_FGCOLOR:       createFill( false )->importDxfFgColor( rStrm );                         break;
2601             case BIFF12_DXF_FILL_BGCOLOR:       createFill( false )->importDxfBgColor( rStrm );                         break;
2602             case BIFF12_DXF_FILL_GRADIENT:      createFill( false )->importDxfGradient( rStrm );                        break;
2603             case BIFF12_DXF_FILL_STOP:          createFill( false )->importDxfStop( rStrm );                            break;
2604             case BIFF12_DXF_FONT_COLOR:         createFont( false )->importDxfColor( rStrm );                           break;
2605             case BIFF12_DXF_BORDER_TOP:         createBorder( false )->importDxfBorder( XLS_TOKEN( top ), rStrm );      break;
2606             case BIFF12_DXF_BORDER_BOTTOM:      createBorder( false )->importDxfBorder( XLS_TOKEN( bottom ), rStrm );   break;
2607             case BIFF12_DXF_BORDER_LEFT:        createBorder( false )->importDxfBorder( XLS_TOKEN( left ), rStrm );     break;
2608             case BIFF12_DXF_BORDER_RIGHT:       createBorder( false )->importDxfBorder( XLS_TOKEN( right ), rStrm );    break;
2609             case BIFF12_DXF_FONT_NAME:          createFont( false )->importDxfName( rStrm );                            break;
2610             case BIFF12_DXF_FONT_WEIGHT:        createFont( false )->importDxfWeight( rStrm );                          break;
2611             case BIFF12_DXF_FONT_UNDERLINE:     createFont( false )->importDxfUnderline( rStrm );                       break;
2612             case BIFF12_DXF_FONT_ESCAPEMENT:    createFont( false )->importDxfEscapement( rStrm );                      break;
2613             case BIFF12_DXF_FONT_ITALIC:        createFont( false )->importDxfFlag( XML_i, rStrm );                     break;
2614             case BIFF12_DXF_FONT_STRIKE:        createFont( false )->importDxfFlag( XML_strike, rStrm );                break;
2615             case BIFF12_DXF_FONT_OUTLINE:       createFont( false )->importDxfFlag( XML_outline, rStrm );               break;
2616             case BIFF12_DXF_FONT_SHADOW:        createFont( false )->importDxfFlag( XML_shadow, rStrm );                break;
2617             case BIFF12_DXF_FONT_HEIGHT:        createFont( false )->importDxfHeight( rStrm );                          break;
2618             case BIFF12_DXF_FONT_SCHEME:        createFont( false )->importDxfScheme( rStrm );                          break;
2619             case BIFF12_DXF_NUMFMT_CODE:        aFmtCode = BiffHelper::readString( rStrm, false );                      break;
2620             case BIFF12_DXF_NUMFMT_ID:          nNumFmtId = rStrm.readuInt16();                                         break;
2621         }
2622         rStrm.seek( nRecEnd );
2623     }
2624     OSL_ENSURE( !rStrm.isEof() && (rStrm.getRemaining() == 0), "Dxf::importDxf - unexpected remaining data" );
2625     mxNumFmt = getStyles().createNumFmt( nNumFmtId, aFmtCode );
2626 }
2627 
2628 void Dxf::importCfRule( BiffInputStream& rStrm, sal_uInt32 nFlags )
2629 {
2630     if( getFlag( nFlags, BIFF_CFRULE_FONTBLOCK ) )
2631         createFont()->importCfRule( rStrm );
2632     if( getFlag( nFlags, BIFF_CFRULE_ALIGNBLOCK ) )
2633         rStrm.skip( 8 );
2634     if( getFlag( nFlags, BIFF_CFRULE_BORDERBLOCK ) )
2635         createBorder()->importCfRule( rStrm, nFlags );
2636     if( getFlag( nFlags, BIFF_CFRULE_FILLBLOCK ) )
2637         createFill()->importCfRule( rStrm, nFlags );
2638     if( getFlag( nFlags, BIFF_CFRULE_PROTBLOCK ) )
2639         rStrm.skip( 2 );
2640 }
2641 
2642 void Dxf::finalizeImport()
2643 {
2644     if( mxFont.get() )
2645         mxFont->finalizeImport();
2646     // number format already finalized by the number formats buffer
2647     if( mxAlignment.get() )
2648         mxAlignment->finalizeImport();
2649     if( mxProtection.get() )
2650         mxProtection->finalizeImport();
2651     if( mxBorder.get() )
2652         mxBorder->finalizeImport();
2653     if( mxFill.get() )
2654         mxFill->finalizeImport();
2655 }
2656 
2657 void Dxf::writeToPropertyMap( PropertyMap& rPropMap ) const
2658 {
2659     if( mxFont.get() )
2660         mxFont->writeToPropertyMap( rPropMap, FONT_PROPTYPE_CELL );
2661     if( mxNumFmt.get() )
2662         mxNumFmt->writeToPropertyMap( rPropMap );
2663     if( mxAlignment.get() )
2664         mxAlignment->writeToPropertyMap( rPropMap );
2665     if( mxProtection.get() )
2666         mxProtection->writeToPropertyMap( rPropMap );
2667     if( mxBorder.get() )
2668         mxBorder->writeToPropertyMap( rPropMap );
2669     if( mxFill.get() )
2670         mxFill->writeToPropertyMap( rPropMap );
2671 }
2672 
2673 void Dxf::writeToPropertySet( PropertySet& rPropSet ) const
2674 {
2675     PropertyMap aPropMap;
2676     writeToPropertyMap( aPropMap );
2677     rPropSet.setProperties( aPropMap );
2678 }
2679 
2680 // ============================================================================
2681 
2682 namespace {
2683 
2684 const sal_Char* const spcLegacyStyleNamePrefix = "Excel_BuiltIn_";
2685 const sal_Char* const sppcLegacyStyleNames[] =
2686 {
2687     "Normal",
2688     "RowLevel_",            // outline level will be appended
2689     "ColumnLevel_",         // outline level will be appended
2690     "Comma",
2691     "Currency",
2692     "Percent",
2693     "Comma_0",              // new in BIFF4
2694     "Currency_0",
2695     "Hyperlink",            // new in BIFF8
2696     "Followed_Hyperlink"
2697 };
2698 const sal_Int32 snLegacyStyleNamesCount = static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( sppcLegacyStyleNames ) );
2699 
2700 const sal_Char* const spcStyleNamePrefix = "Excel Built-in ";
2701 const sal_Char* const sppcStyleNames[] =
2702 {
2703     "Normal",
2704     "RowLevel_",            // outline level will be appended
2705     "ColLevel_",            // outline level will be appended
2706     "Comma",
2707     "Currency",
2708     "Percent",
2709     "Comma [0]",            // new in BIFF4
2710     "Currency [0]",
2711     "Hyperlink",            // new in BIFF8
2712     "Followed Hyperlink",
2713     "Note",                 // new in OOX
2714     "Warning Text",
2715     0,
2716     0,
2717     0,
2718     "Title",
2719     "Heading 1",
2720     "Heading 2",
2721     "Heading 3",
2722     "Heading 4",
2723     "Input",
2724     "Output",
2725     "Calculation",
2726     "Check Cell",
2727     "Linked Cell",
2728     "Total",
2729     "Good",
2730     "Bad",
2731     "Neutral",
2732     "Accent1",
2733     "20% - Accent1",
2734     "40% - Accent1",
2735     "60% - Accent1",
2736     "Accent2",
2737     "20% - Accent2",
2738     "40% - Accent2",
2739     "60% - Accent2",
2740     "Accent3",
2741     "20% - Accent3",
2742     "40% - Accent3",
2743     "60% - Accent3",
2744     "Accent4",
2745     "20% - Accent4",
2746     "40% - Accent4",
2747     "60% - Accent4",
2748     "Accent5",
2749     "20% - Accent5",
2750     "40% - Accent5",
2751     "60% - Accent5",
2752     "Accent6",
2753     "20% - Accent6",
2754     "40% - Accent6",
2755     "60% - Accent6",
2756     "Explanatory Text"
2757 };
2758 const sal_Int32 snStyleNamesCount = static_cast< sal_Int32 >( STATIC_ARRAY_SIZE( sppcStyleNames ) );
2759 
2760 OUString lclGetBuiltinStyleName( sal_Int32 nBuiltinId, const OUString& rName, sal_Int32 nLevel = 0 )
2761 {
2762     OSL_ENSURE( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount), "lclGetBuiltinStyleName - unknown built-in style" );
2763     OUStringBuffer aStyleName;
2764     aStyleName.appendAscii( spcStyleNamePrefix );
2765     if( (0 <= nBuiltinId) && (nBuiltinId < snStyleNamesCount) && (sppcStyleNames[ nBuiltinId ] != 0) )
2766         aStyleName.appendAscii( sppcStyleNames[ nBuiltinId ] );
2767     else if( rName.getLength() > 0 )
2768         aStyleName.append( rName );
2769     else
2770         aStyleName.append( nBuiltinId );
2771     if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) )
2772         aStyleName.append( nLevel );
2773     return aStyleName.makeStringAndClear();
2774 }
2775 
2776 OUString lclCreateStyleName( const CellStyleModel& rModel )
2777 {
2778     return rModel.mbBuiltin ? lclGetBuiltinStyleName( rModel.mnBuiltinId, rModel.maName, rModel.mnLevel ) : rModel.maName;
2779 }
2780 
2781 bool lclIsBuiltinStyleName( const OUString& rStyleName, sal_Int32* pnBuiltinId, sal_Int32* pnNextChar )
2782 {
2783     // try the other built-in styles
2784     OUString aPrefix = OUString::createFromAscii( spcStyleNamePrefix );
2785     sal_Int32 nPrefixLen = aPrefix.getLength();
2786     sal_Int32 nFoundId = 0;
2787     sal_Int32 nNextChar = 0;
2788     if( rStyleName.matchIgnoreAsciiCase( aPrefix ) )
2789     {
2790         OUString aShortName;
2791         for( sal_Int32 nId = 0; nId < snStyleNamesCount; ++nId )
2792         {
2793             if( sppcStyleNames[ nId ] != 0 )
2794             {
2795                 aShortName = OUString::createFromAscii( sppcStyleNames[ nId ] );
2796                 if( rStyleName.matchIgnoreAsciiCase( aShortName, nPrefixLen ) &&
2797                         (nNextChar < nPrefixLen + aShortName.getLength()) )
2798                 {
2799                     nFoundId = nId;
2800                     nNextChar = nPrefixLen + aShortName.getLength();
2801                 }
2802             }
2803         }
2804     }
2805 
2806     if( nNextChar > 0 )
2807     {
2808         if( pnBuiltinId ) *pnBuiltinId = nFoundId;
2809         if( pnNextChar ) *pnNextChar = nNextChar;
2810         return true;
2811     }
2812 
2813     if( pnBuiltinId ) *pnBuiltinId = -1;
2814     if( pnNextChar ) *pnNextChar = 0;
2815     return false;
2816 }
2817 
2818 bool lclGetBuiltinStyleId( sal_Int32& rnBuiltinId, sal_Int32& rnLevel, const OUString& rStyleName )
2819 {
2820     sal_Int32 nBuiltinId;
2821     sal_Int32 nNextChar;
2822     if( lclIsBuiltinStyleName( rStyleName, &nBuiltinId, &nNextChar ) )
2823     {
2824         if( (nBuiltinId == OOX_STYLE_ROWLEVEL) || (nBuiltinId == OOX_STYLE_COLLEVEL) )
2825         {
2826             OUString aLevel = rStyleName.copy( nNextChar );
2827             sal_Int32 nLevel = aLevel.toInt32();
2828             if( (0 < nLevel) && (nLevel <= OOX_STYLE_LEVELCOUNT) )
2829             {
2830                 rnBuiltinId = nBuiltinId;
2831                 rnLevel = nLevel;
2832                 return true;
2833             }
2834         }
2835         else if( rStyleName.getLength() == nNextChar )
2836         {
2837             rnBuiltinId = nBuiltinId;
2838             rnLevel = 0;
2839             return true;
2840         }
2841     }
2842     rnBuiltinId = -1;
2843     rnLevel = 0;
2844     return false;
2845 }
2846 
2847 } // namespace
2848 
2849 // ----------------------------------------------------------------------------
2850 
2851 CellStyleModel::CellStyleModel() :
2852     mnXfId( -1 ),
2853     mnBuiltinId( -1 ),
2854     mnLevel( 0 ),
2855     mbBuiltin( false ),
2856     mbCustom( false ),
2857     mbHidden( false )
2858 {
2859 }
2860 
2861 bool CellStyleModel::isBuiltin() const
2862 {
2863     return mbBuiltin && (mnBuiltinId >= 0);
2864 }
2865 
2866 bool CellStyleModel::isDefaultStyle() const
2867 {
2868     return mbBuiltin && (mnBuiltinId == OOX_STYLE_NORMAL);
2869 }
2870 
2871 // ============================================================================
2872 
2873 CellStyle::CellStyle( const WorkbookHelper& rHelper ) :
2874     WorkbookHelper( rHelper ),
2875     mbCreated( false )
2876 {
2877 }
2878 
2879 void CellStyle::importCellStyle( const AttributeList& rAttribs )
2880 {
2881     maModel.maName      = rAttribs.getXString( XML_name, OUString() );
2882     maModel.mnXfId      = rAttribs.getInteger( XML_xfId, -1 );
2883     maModel.mnBuiltinId = rAttribs.getInteger( XML_builtinId, -1 );
2884     maModel.mnLevel     = rAttribs.getInteger( XML_iLevel, 0 );
2885     maModel.mbBuiltin   = rAttribs.hasAttribute( XML_builtinId );
2886     maModel.mbCustom    = rAttribs.getBool( XML_customBuiltin, false );
2887     maModel.mbHidden    = rAttribs.getBool( XML_hidden, false );
2888 }
2889 
2890 void CellStyle::importCellStyle( SequenceInputStream& rStrm )
2891 {
2892     sal_uInt16 nFlags;
2893     rStrm >> maModel.mnXfId >> nFlags;
2894     maModel.mnBuiltinId = rStrm.readInt8();
2895     maModel.mnLevel = rStrm.readInt8();
2896     rStrm >> maModel.maName;
2897     maModel.mbBuiltin = getFlag( nFlags, BIFF12_CELLSTYLE_BUILTIN );
2898     maModel.mbCustom = getFlag( nFlags, BIFF12_CELLSTYLE_CUSTOM );
2899     maModel.mbHidden = getFlag( nFlags, BIFF12_CELLSTYLE_HIDDEN );
2900 }
2901 
2902 void CellStyle::importStyle( BiffInputStream& rStrm )
2903 {
2904     sal_uInt16 nStyleXf;
2905     rStrm >> nStyleXf;
2906     maModel.mnXfId = static_cast< sal_Int32 >( nStyleXf & BIFF_STYLE_XFMASK );
2907     maModel.mbBuiltin = getFlag( nStyleXf, BIFF_STYLE_BUILTIN );
2908     if( maModel.mbBuiltin )
2909     {
2910         maModel.mnBuiltinId = rStrm.readInt8();
2911         maModel.mnLevel = rStrm.readInt8();
2912     }
2913     else
2914     {
2915         maModel.maName = (getBiff() == BIFF8) ?
2916             rStrm.readUniString() : rStrm.readByteStringUC( false, getTextEncoding() );
2917         // #i103281# check if this is a new built-in style introduced in XL2007
2918         if( (getBiff() == BIFF8) && (rStrm.getNextRecId() == BIFF_ID_STYLEEXT) && rStrm.startNextRecord() )
2919         {
2920             sal_uInt8 nExtFlags;
2921             rStrm.skip( 12 );
2922             rStrm >> nExtFlags;
2923             maModel.mbBuiltin = getFlag( nExtFlags, BIFF_STYLEEXT_BUILTIN );
2924             maModel.mbCustom = getFlag( nExtFlags, BIFF_STYLEEXT_CUSTOM );
2925             maModel.mbHidden = getFlag( nExtFlags, BIFF_STYLEEXT_HIDDEN );
2926             if( maModel.mbBuiltin )
2927             {
2928                 maModel.mnBuiltinId = rStrm.readInt8();
2929                 maModel.mnLevel = rStrm.readInt8();
2930             }
2931         }
2932     }
2933 }
2934 
2935 void CellStyle::createCellStyle()
2936 {
2937     // #i1624# #i1768# ignore unnamed user styles
2938     if( !mbCreated )
2939         mbCreated = maFinalName.getLength() == 0;
2940 
2941     /*  #i103281# do not create another style of the same name, if it exists
2942         already. This is needed to prevent that styles pasted from clipboard
2943         get duplicated over and over. */
2944     if( !mbCreated ) try
2945     {
2946         Reference< XNameAccess > xCellStylesNA( getStyleFamily( false ), UNO_QUERY_THROW );
2947         mbCreated = xCellStylesNA->hasByName( maFinalName );
2948     }
2949     catch( Exception& )
2950     {
2951     }
2952 
2953     // create the style object in the document
2954     if( !mbCreated ) try
2955     {
2956         mbCreated = true;
2957         Reference< XStyle > xStyle( createStyleObject( maFinalName, false ), UNO_SET_THROW );
2958         // write style formatting properties
2959         PropertySet aPropSet( xStyle );
2960         getStyles().writeStyleXfToPropertySet( aPropSet, maModel.mnXfId );
2961         if( !maModel.isDefaultStyle() )
2962             xStyle->setParentStyle( getStyles().getDefaultStyleName() );
2963     }
2964     catch( Exception& )
2965     {
2966     }
2967 }
2968 
2969 void CellStyle::finalizeImport( const OUString& rFinalName )
2970 {
2971     maFinalName = rFinalName;
2972     if( !maModel.isBuiltin() || maModel.mbCustom )
2973         createCellStyle();
2974 }
2975 
2976 // ============================================================================
2977 
2978 CellStyleBuffer::CellStyleBuffer( const WorkbookHelper& rHelper ) :
2979     WorkbookHelper( rHelper )
2980 {
2981 }
2982 
2983 CellStyleRef CellStyleBuffer::importCellStyle( const AttributeList& rAttribs )
2984 {
2985     CellStyleRef xCellStyle( new CellStyle( *this ) );
2986     xCellStyle->importCellStyle( rAttribs );
2987     insertCellStyle( xCellStyle );
2988     return xCellStyle;
2989 }
2990 
2991 CellStyleRef CellStyleBuffer::importCellStyle( SequenceInputStream& rStrm )
2992 {
2993     CellStyleRef xCellStyle( new CellStyle( *this ) );
2994     xCellStyle->importCellStyle( rStrm );
2995     insertCellStyle( xCellStyle );
2996     return xCellStyle;
2997 }
2998 
2999 CellStyleRef CellStyleBuffer::importStyle( BiffInputStream& rStrm )
3000 {
3001     CellStyleRef xCellStyle( new CellStyle( *this ) );
3002     xCellStyle->importStyle( rStrm );
3003     insertCellStyle( xCellStyle );
3004     return xCellStyle;
3005 }
3006 
3007 void CellStyleBuffer::finalizeImport()
3008 {
3009     // calculate final names of all styles
3010     typedef RefMap< OUString, CellStyle, IgnoreCaseCompare > CellStyleNameMap;
3011     CellStyleNameMap aCellStyles;
3012     CellStyleVector aConflictNameStyles;
3013 
3014     /*  First, reserve style names that are built-in in Calc. This causes that
3015         imported cell styles get different unused names and thus do not try to
3016         overwrite these built-in styles. For BIFF4 workbooks (which contain a
3017         separate list of cell styles per sheet), reserve all existing styles if
3018         current sheet is not the first sheet (this styles buffer will be
3019         constructed again for every new sheet). This will create unique names
3020         for styles in different sheets with the same name. Assuming that the
3021         BIFF4W import filter is never used to import from clipboard... */
3022     bool bReserveAll = (getFilterType() == FILTER_BIFF) && (getBiff() == BIFF4) && isWorkbookFile() && (getCurrentSheetIndex() > 0);
3023     try
3024     {
3025         // unfortunately, com.sun.star.style.StyleFamily does not implement XEnumerationAccess...
3026         Reference< XIndexAccess > xStyleFamilyIA( getStyleFamily( false ), UNO_QUERY_THROW );
3027         for( sal_Int32 nIndex = 0, nCount = xStyleFamilyIA->getCount(); nIndex < nCount; ++nIndex )
3028         {
3029             Reference< XStyle > xStyle( xStyleFamilyIA->getByIndex( nIndex ), UNO_QUERY_THROW );
3030             if( bReserveAll || !xStyle->isUserDefined() )
3031             {
3032                 Reference< XNamed > xStyleName( xStyle, UNO_QUERY_THROW );
3033                 // create an empty entry by using ::std::map<>::operator[]
3034                 aCellStyles[ xStyleName->getName() ];
3035             }
3036         }
3037     }
3038     catch( Exception& )
3039     {
3040     }
3041 
3042     /*  Calculate names of built-in styles. Store styles with reserved names
3043         in the aConflictNameStyles list. */
3044     for( CellStyleVector::iterator aIt = maBuiltinStyles.begin(), aEnd = maBuiltinStyles.end(); aIt != aEnd; ++aIt )
3045     {
3046         const CellStyleModel& rModel = (*aIt)->getModel();
3047         OUString aStyleName = lclCreateStyleName( rModel );
3048         /*  If a builtin style entry already exists, and we do not reserve all
3049             existing styles, we just stick with the last definition and ignore
3050             the preceding ones. */
3051         if( bReserveAll && (aCellStyles.count( aStyleName ) > 0) )
3052             aConflictNameStyles.push_back( *aIt );
3053         else
3054             aCellStyles[ aStyleName ] = *aIt;
3055     }
3056 
3057     /*  Calculate names of user defined styles. Store styles with reserved
3058         names in the aConflictNameStyles list. */
3059     for( CellStyleVector::iterator aIt = maUserStyles.begin(), aEnd = maUserStyles.end(); aIt != aEnd; ++aIt )
3060     {
3061         const CellStyleModel& rModel = (*aIt)->getModel();
3062         OUString aStyleName = lclCreateStyleName( rModel );
3063         // #i1624# #i1768# ignore unnamed user styles
3064         if( aStyleName.getLength() > 0 )
3065         {
3066             if( aCellStyles.count( aStyleName ) > 0 )
3067                 aConflictNameStyles.push_back( *aIt );
3068             else
3069                 aCellStyles[ aStyleName ] = *aIt;
3070         }
3071     }
3072 
3073     // find unused names for all styles with conflicting names
3074     for( CellStyleVector::iterator aIt = aConflictNameStyles.begin(), aEnd = aConflictNameStyles.end(); aIt != aEnd; ++aIt )
3075     {
3076         const CellStyleModel& rModel = (*aIt)->getModel();
3077         OUString aStyleName = lclCreateStyleName( rModel );
3078         OUString aUnusedName;
3079         sal_Int32 nIndex = 0;
3080         do
3081         {
3082             aUnusedName = OUStringBuffer( aStyleName ).append( sal_Unicode( ' ' ) ).append( ++nIndex ).makeStringAndClear();
3083         }
3084         while( aCellStyles.count( aUnusedName ) > 0 );
3085         aCellStyles[ aUnusedName ] = *aIt;
3086     }
3087 
3088     // set final names and create user-defined and modified built-in cell styles
3089     aCellStyles.forEachMemWithKey( &CellStyle::finalizeImport );
3090 }
3091 
3092 sal_Int32 CellStyleBuffer::getDefaultXfId() const
3093 {
3094     return mxDefStyle.get() ? mxDefStyle->getModel().mnXfId : -1;
3095 }
3096 
3097 OUString CellStyleBuffer::getDefaultStyleName() const
3098 {
3099     return createCellStyle( mxDefStyle );
3100 }
3101 
3102 OUString CellStyleBuffer::createCellStyle( sal_Int32 nXfId ) const
3103 {
3104     return createCellStyle( maStylesByXf.get( nXfId ) );
3105 }
3106 
3107 // private --------------------------------------------------------------------
3108 
3109 void CellStyleBuffer::insertCellStyle( CellStyleRef xCellStyle )
3110 {
3111     const CellStyleModel& rModel = xCellStyle->getModel();
3112     if( rModel.mnXfId >= 0 )
3113     {
3114         // insert into the built-in map or user defined map
3115         (rModel.isBuiltin() ? maBuiltinStyles : maUserStyles).push_back( xCellStyle );
3116 
3117         // insert into the XF identifier map
3118         OSL_ENSURE( maStylesByXf.count( rModel.mnXfId ) == 0, "CellStyleBuffer::insertCellStyle - multiple styles with equal XF identifier" );
3119         maStylesByXf[ rModel.mnXfId ] = xCellStyle;
3120 
3121         // remember default cell style
3122         if( rModel.isDefaultStyle() )
3123             mxDefStyle = xCellStyle;
3124     }
3125 }
3126 
3127 OUString CellStyleBuffer::createCellStyle( const CellStyleRef& rxCellStyle ) const
3128 {
3129     if( rxCellStyle.get() )
3130     {
3131         rxCellStyle->createCellStyle();
3132         const OUString& rStyleName = rxCellStyle->getFinalStyleName();
3133         if( rStyleName.getLength() > 0 )
3134             return rStyleName;
3135     }
3136     // on error: fallback to default style
3137     return lclGetBuiltinStyleName( OOX_STYLE_NORMAL, OUString() );
3138 }
3139 
3140 // ============================================================================
3141 
3142 AutoFormatModel::AutoFormatModel() :
3143     mnAutoFormatId( 0 ),
3144     mbApplyNumFmt( false ),
3145     mbApplyFont( false ),
3146     mbApplyAlignment( false ),
3147     mbApplyBorder( false ),
3148     mbApplyFill( false ),
3149     mbApplyProtection( false )
3150 {
3151 }
3152 
3153 // ============================================================================
3154 
3155 StylesBuffer::StylesBuffer( const WorkbookHelper& rHelper ) :
3156     WorkbookHelper( rHelper ),
3157     maPalette( rHelper ),
3158     maNumFmts( rHelper ),
3159     maCellStyles( rHelper )
3160 {
3161 }
3162 
3163 FontRef StylesBuffer::createFont( sal_Int32* opnFontId )
3164 {
3165     if( opnFontId ) *opnFontId = static_cast< sal_Int32 >( maFonts.size() );
3166     FontRef xFont( new Font( *this, false ) );
3167     maFonts.push_back( xFont );
3168     return xFont;
3169 }
3170 
3171 NumberFormatRef StylesBuffer::createNumFmt( sal_Int32 nNumFmtId, const OUString& rFmtCode )
3172 {
3173     return maNumFmts.createNumFmt( nNumFmtId, rFmtCode );
3174 }
3175 
3176 BorderRef StylesBuffer::createBorder( sal_Int32* opnBorderId )
3177 {
3178     if( opnBorderId ) *opnBorderId = static_cast< sal_Int32 >( maBorders.size() );
3179     BorderRef xBorder( new Border( *this, false ) );
3180     maBorders.push_back( xBorder );
3181     return xBorder;
3182 }
3183 
3184 FillRef StylesBuffer::createFill( sal_Int32* opnFillId )
3185 {
3186     if( opnFillId ) *opnFillId = static_cast< sal_Int32 >( maFills.size() );
3187     FillRef xFill( new Fill( *this, false ) );
3188     maFills.push_back( xFill );
3189     return xFill;
3190 }
3191 
3192 XfRef StylesBuffer::createCellXf( sal_Int32* opnXfId )
3193 {
3194     if( opnXfId ) *opnXfId = static_cast< sal_Int32 >( maCellXfs.size() );
3195     XfRef xXf( new Xf( *this ) );
3196     maCellXfs.push_back( xXf );
3197     return xXf;
3198 }
3199 
3200 XfRef StylesBuffer::createStyleXf( sal_Int32* opnXfId )
3201 {
3202     if( opnXfId ) *opnXfId = static_cast< sal_Int32 >( maStyleXfs.size() );
3203     XfRef xXf( new Xf( *this ) );
3204     maStyleXfs.push_back( xXf );
3205     return xXf;
3206 }
3207 
3208 DxfRef StylesBuffer::createDxf( sal_Int32* opnDxfId )
3209 {
3210     if( opnDxfId ) *opnDxfId = static_cast< sal_Int32 >( maDxfs.size() );
3211     DxfRef xDxf( new Dxf( *this ) );
3212     maDxfs.push_back( xDxf );
3213     return xDxf;
3214 }
3215 
3216 void StylesBuffer::importPaletteColor( const AttributeList& rAttribs )
3217 {
3218     maPalette.importPaletteColor( rAttribs );
3219 }
3220 
3221 NumberFormatRef StylesBuffer::importNumFmt( const AttributeList& rAttribs )
3222 {
3223     return maNumFmts.importNumFmt( rAttribs );
3224 }
3225 
3226 CellStyleRef StylesBuffer::importCellStyle( const AttributeList& rAttribs )
3227 {
3228     return maCellStyles.importCellStyle( rAttribs );
3229 }
3230 
3231 void StylesBuffer::importPaletteColor( SequenceInputStream& rStrm )
3232 {
3233     maPalette.importPaletteColor( rStrm );
3234 }
3235 
3236 void StylesBuffer::importNumFmt( SequenceInputStream& rStrm )
3237 {
3238     maNumFmts.importNumFmt( rStrm );
3239 }
3240 
3241 void StylesBuffer::importCellStyle( SequenceInputStream& rStrm )
3242 {
3243     maCellStyles.importCellStyle( rStrm );
3244 }
3245 
3246 void StylesBuffer::importPalette( BiffInputStream& rStrm )
3247 {
3248     maPalette.importPalette( rStrm );
3249 }
3250 
3251 void StylesBuffer::importFont( BiffInputStream& rStrm )
3252 {
3253     /* Font with index 4 is not stored in BIFF. This means effectively, first
3254         font in the BIFF file has index 0, fourth font has index 3, and fifth
3255         font has index 5. Insert a dummy font to correctly map passed font
3256         identifiers. */
3257     if( maFonts.size() == 4 )
3258         maFonts.push_back( maFonts.front() );
3259 
3260     FontRef xFont = createFont();
3261     xFont->importFont( rStrm );
3262 
3263     /*  #i71033# Set stream text encoding from application font, if CODEPAGE
3264         record is missing. Must be done now (not while finalizeImport() runs),
3265         to be able to read all following byte strings correctly (e.g. cell
3266         style names). */
3267     if( maFonts.size() == 1 )
3268         setAppFontEncoding( xFont->getFontEncoding() );
3269 }
3270 
3271 void StylesBuffer::importFontColor( BiffInputStream& rStrm )
3272 {
3273     if( !maFonts.empty() )
3274         maFonts.back()->importFontColor( rStrm );
3275 }
3276 
3277 void StylesBuffer::importFormat( BiffInputStream& rStrm )
3278 {
3279     maNumFmts.importFormat( rStrm );
3280 }
3281 
3282 void StylesBuffer::importXf( BiffInputStream& rStrm )
3283 {
3284     XfRef xXf( new Xf( *this ) );
3285     xXf->importXf( rStrm );
3286 
3287     XfRef xCellXf, xStyleXf;
3288     (xXf->isCellXf() ? xCellXf : xStyleXf) = xXf;
3289     maCellXfs.push_back( xCellXf );
3290     maStyleXfs.push_back( xStyleXf );
3291 }
3292 
3293 void StylesBuffer::importStyle( BiffInputStream& rStrm )
3294 {
3295     maCellStyles.importStyle( rStrm );
3296 }
3297 
3298 void StylesBuffer::importPalette( const Any& rPalette )
3299 {
3300     maPalette.importPalette( rPalette );
3301 }
3302 
3303 void StylesBuffer::finalizeImport()
3304 {
3305     // fonts first, are needed to finalize unit converter and XFs below
3306     maFonts.forEachMem( &Font::finalizeImport );
3307     // finalize unit coefficients after default font is known
3308     getUnitConverter().finalizeImport();
3309     // number formats
3310     maNumFmts.finalizeImport();
3311     // borders and fills
3312     maBorders.forEachMem( &Border::finalizeImport );
3313     maFills.forEachMem( &Fill::finalizeImport );
3314     // style XFs and cell XFs
3315     maStyleXfs.forEachMem( &Xf::finalizeImport );
3316     maCellXfs.forEachMem( &Xf::finalizeImport );
3317     // built-in and user defined cell styles
3318     maCellStyles.finalizeImport();
3319     // differential formatting (for conditional formatting)
3320     maDxfs.forEachMem( &Dxf::finalizeImport );
3321 }
3322 
3323 sal_Int32 StylesBuffer::getPaletteColor( sal_Int32 nPaletteIdx ) const
3324 {
3325     return maPalette.getColor( nPaletteIdx );
3326 }
3327 
3328 FontRef StylesBuffer::getFont( sal_Int32 nFontId ) const
3329 {
3330     return maFonts.get( nFontId );
3331 }
3332 
3333 BorderRef StylesBuffer::getBorder( sal_Int32 nBorderId ) const
3334 {
3335     return maBorders.get( nBorderId );
3336 }
3337 
3338 XfRef StylesBuffer::getCellXf( sal_Int32 nXfId ) const
3339 {
3340     return maCellXfs.get( nXfId );
3341 }
3342 
3343 XfRef StylesBuffer::getStyleXf( sal_Int32 nXfId ) const
3344 {
3345     return maStyleXfs.get( nXfId );
3346 }
3347 
3348 DxfRef StylesBuffer::getDxf( sal_Int32 nDxfId ) const
3349 {
3350     return maDxfs.get( nDxfId );
3351 }
3352 
3353 FontRef StylesBuffer::getFontFromCellXf( sal_Int32 nXfId ) const
3354 {
3355     FontRef xFont;
3356     if( const Xf* pXf = getCellXf( nXfId ).get() )
3357         xFont = pXf->getFont();
3358     return xFont;
3359 }
3360 
3361 FontRef StylesBuffer::getDefaultFont() const
3362 {
3363     FontRef xDefFont;
3364     if( const Xf* pXf = getStyleXf( maCellStyles.getDefaultXfId() ).get() )
3365         xDefFont = pXf->getFont();
3366     // no font from styles - try first loaded font (e.g. BIFF2)
3367     if( !xDefFont )
3368         xDefFont = maFonts.get( 0 );
3369     OSL_ENSURE( xDefFont.get(), "StylesBuffer::getDefaultFont - no default font found" );
3370     return xDefFont;
3371 }
3372 
3373 const FontModel& StylesBuffer::getDefaultFontModel() const
3374 {
3375     FontRef xDefFont = getDefaultFont();
3376     return xDefFont.get() ? xDefFont->getModel() : getTheme().getDefaultFontModel();
3377 }
3378 
3379 bool StylesBuffer::equalBorders( sal_Int32 nBorderId1, sal_Int32 nBorderId2 ) const
3380 {
3381     if( nBorderId1 == nBorderId2 )
3382         return true;
3383 
3384     switch( getFilterType() )
3385     {
3386         case FILTER_OOXML:
3387             // in OOXML, borders are assumed to be unique
3388             return false;
3389 
3390         case FILTER_BIFF:
3391         {
3392             // in BIFF, a new border entry has been created for every XF
3393             const Border* pBorder1 = maBorders.get( nBorderId1 ).get();
3394             const Border* pBorder2 = maBorders.get( nBorderId2 ).get();
3395             return pBorder1 && pBorder2 && (pBorder1->getApiData() == pBorder2->getApiData());
3396         }
3397 
3398         case FILTER_UNKNOWN:
3399         break;
3400     }
3401     return false;
3402 }
3403 
3404 bool StylesBuffer::equalFills( sal_Int32 nFillId1, sal_Int32 nFillId2 ) const
3405 {
3406     if( nFillId1 == nFillId2 )
3407         return true;
3408 
3409     switch( getFilterType() )
3410     {
3411         case FILTER_OOXML:
3412             // in OOXML, fills are assumed to be unique
3413             return false;
3414 
3415         case FILTER_BIFF:
3416         {
3417             // in BIFF, a new fill entry has been created for every XF
3418             const Fill* pFill1 = maFills.get( nFillId1 ).get();
3419             const Fill* pFill2 = maFills.get( nFillId2 ).get();
3420             return pFill1 && pFill2 && (pFill1->getApiData() == pFill2->getApiData());
3421         }
3422 
3423         case FILTER_UNKNOWN:
3424         break;
3425     }
3426     return false;
3427 }
3428 
3429 OUString StylesBuffer::getDefaultStyleName() const
3430 {
3431     return maCellStyles.getDefaultStyleName();
3432 }
3433 
3434 OUString StylesBuffer::createCellStyle( sal_Int32 nXfId ) const
3435 {
3436     return maCellStyles.createCellStyle( nXfId );
3437 }
3438 
3439 OUString StylesBuffer::createDxfStyle( sal_Int32 nDxfId ) const
3440 {
3441     OUString& rStyleName = maDxfStyles[ nDxfId ];
3442     if( rStyleName.getLength() == 0 )
3443     {
3444         if( Dxf* pDxf = maDxfs.get( nDxfId ).get() )
3445         {
3446             rStyleName = OUStringBuffer( CREATE_OUSTRING( "ConditionalStyle_" ) ).append( nDxfId + 1 ).makeStringAndClear();
3447             // create the style sheet (this may change rStyleName if such a style already exists)
3448             Reference< XStyle > xStyle = createStyleObject( rStyleName, false );
3449             // write style formatting properties
3450             PropertySet aPropSet( xStyle );
3451             pDxf->writeToPropertySet( aPropSet );
3452         }
3453         // on error: fallback to default style
3454         if( rStyleName.getLength() == 0 )
3455             rStyleName = maCellStyles.getDefaultStyleName();
3456     }
3457     return rStyleName;
3458 }
3459 
3460 void StylesBuffer::writeFontToPropertyMap( PropertyMap& rPropMap, sal_Int32 nFontId ) const
3461 {
3462     if( Font* pFont = maFonts.get( nFontId ).get() )
3463         pFont->writeToPropertyMap( rPropMap, FONT_PROPTYPE_CELL );
3464 }
3465 
3466 void StylesBuffer::writeNumFmtToPropertyMap( PropertyMap& rPropMap, sal_Int32 nNumFmtId ) const
3467 {
3468     maNumFmts.writeToPropertyMap( rPropMap, nNumFmtId );
3469 }
3470 
3471 void StylesBuffer::writeBorderToPropertyMap( PropertyMap& rPropMap, sal_Int32 nBorderId ) const
3472 {
3473     if( Border* pBorder = maBorders.get( nBorderId ).get() )
3474         pBorder->writeToPropertyMap( rPropMap );
3475 }
3476 
3477 void StylesBuffer::writeFillToPropertyMap( PropertyMap& rPropMap, sal_Int32 nFillId ) const
3478 {
3479     if( Fill* pFill = maFills.get( nFillId ).get() )
3480         pFill->writeToPropertyMap( rPropMap );
3481 }
3482 
3483 void StylesBuffer::writeCellXfToPropertyMap( PropertyMap& rPropMap, sal_Int32 nXfId ) const
3484 {
3485     if( Xf* pXf = maCellXfs.get( nXfId ).get() )
3486         pXf->writeToPropertyMap( rPropMap );
3487 }
3488 
3489 void StylesBuffer::writeStyleXfToPropertyMap( PropertyMap& rPropMap, sal_Int32 nXfId ) const
3490 {
3491     if( Xf* pXf = maStyleXfs.get( nXfId ).get() )
3492         pXf->writeToPropertyMap( rPropMap );
3493 }
3494 
3495 void StylesBuffer::writeCellXfToPropertySet( PropertySet& rPropSet, sal_Int32 nXfId ) const
3496 {
3497     if( Xf* pXf = maCellXfs.get( nXfId ).get() )
3498         pXf->writeToPropertySet( rPropSet );
3499 }
3500 
3501 void StylesBuffer::writeStyleXfToPropertySet( PropertySet& rPropSet, sal_Int32 nXfId ) const
3502 {
3503     if( Xf* pXf = maStyleXfs.get( nXfId ).get() )
3504         pXf->writeToPropertySet( rPropSet );
3505 }
3506 
3507 // ============================================================================
3508 
3509 } // namespace xls
3510 } // namespace oox
3511