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