bump product version to 4.1.6.2
[LibreOffice.git] / sc / source / filter / excel / xistyle.cxx
bloba22ef9b08dfb198e566be2ee30d46d488492c609
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "xistyle.hxx"
21 #include <sfx2/printer.hxx>
22 #include <sfx2/objsh.hxx>
23 #include <svtools/ctrltool.hxx>
24 #include <editeng/editobj.hxx>
25 #include "scitems.hxx"
26 #include <editeng/fontitem.hxx>
27 #include <editeng/fhgtitem.hxx>
28 #include <editeng/wghtitem.hxx>
29 #include <editeng/udlnitem.hxx>
30 #include <editeng/postitem.hxx>
31 #include <editeng/crossedoutitem.hxx>
32 #include <editeng/contouritem.hxx>
33 #include <editeng/shdditem.hxx>
34 #include <editeng/escapementitem.hxx>
35 #include <svx/algitem.hxx>
36 #include <editeng/boxitem.hxx>
37 #include <editeng/lineitem.hxx>
38 #include <svx/rotmodit.hxx>
39 #include <editeng/colritem.hxx>
40 #include <editeng/brushitem.hxx>
41 #include <editeng/frmdiritem.hxx>
42 #include <editeng/eeitem.hxx>
43 #include <editeng/flstitem.hxx>
44 #include <editeng/justifyitem.hxx>
45 #include <sal/macros.h>
46 #include "document.hxx"
47 #include "docpool.hxx"
48 #include "attrib.hxx"
49 #include "stlpool.hxx"
50 #include "stlsheet.hxx"
51 #include "formulacell.hxx"
52 #include "globstr.hrc"
53 #include "attarray.hxx"
54 #include "xltracer.hxx"
55 #include "xistream.hxx"
56 #include "xicontent.hxx"
58 #include "root.hxx"
59 #include "colrowst.hxx"
60 #include "svl/poolcach.hxx"
62 #include <list>
64 using ::std::list;
66 #include <cppuhelper/implbase1.hxx>
67 #include <com/sun/star/container/XIndexAccess.hpp>
68 #include <com/sun/star/beans/XPropertySet.hpp>
69 using namespace ::com::sun::star;
71 typedef ::cppu::WeakImplHelper1< container::XIndexAccess > XIndexAccess_BASE;
72 typedef ::std::vector< ColorData > ColorDataVec;
74 class PaletteIndex : public XIndexAccess_BASE
76 public:
77 PaletteIndex( const ColorDataVec& rColorDataTable ) : maColorData( rColorDataTable ) {}
79 // Methods XIndexAccess
80 virtual ::sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException)
82 return maColorData.size();
85 virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException)
87 //--Index; // apparently the palette is already 1 based
88 return uno::makeAny( sal_Int32( maColorData[ Index ] ) );
91 // Methods XElementAcess
92 virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException)
94 return ::getCppuType( (sal_Int32*)0 );
96 virtual ::sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException)
98 return (maColorData.size() > 0);
101 private:
102 ColorDataVec maColorData;
105 void
106 XclImpPalette::ExportPalette()
108 if( SfxObjectShell* pDocShell = mrRoot.GetDocShell() )
110 // copy values in color palette
111 sal_Int16 nColors = maColorTable.size();
112 ColorDataVec aColors;
113 aColors.resize( nColors );
114 for( sal_uInt16 nIndex = 0; nIndex < nColors; ++nIndex )
115 aColors[ nIndex ] = GetColorData( nIndex );
117 uno::Reference< beans::XPropertySet > xProps( pDocShell->GetModel(), uno::UNO_QUERY );
118 if ( xProps.is() )
120 uno::Reference< container::XIndexAccess > xIndex( new PaletteIndex( aColors ) );
121 xProps->setPropertyValue( "ColorPalette", uno::makeAny( xIndex ) );
126 // PALETTE record - color information =========================================
128 XclImpPalette::XclImpPalette( const XclImpRoot& rRoot ) :
129 XclDefaultPalette( rRoot ), mrRoot( rRoot )
133 void XclImpPalette::Initialize()
135 maColorTable.clear();
138 ColorData XclImpPalette::GetColorData( sal_uInt16 nXclIndex ) const
140 if( nXclIndex >= EXC_COLOR_USEROFFSET )
142 sal_uInt32 nIx = nXclIndex - EXC_COLOR_USEROFFSET;
143 if( nIx < maColorTable.size() )
144 return maColorTable[ nIx ];
146 return GetDefColorData( nXclIndex );
149 void XclImpPalette::ReadPalette( XclImpStream& rStrm )
151 sal_uInt16 nCount;
152 rStrm >> nCount;
153 OSL_ENSURE( rStrm.GetRecLeft() == static_cast< sal_Size >( 4 * nCount ),
154 "XclImpPalette::ReadPalette - size mismatch" );
156 maColorTable.resize( nCount );
157 Color aColor;
158 for( sal_uInt16 nIndex = 0; nIndex < nCount; ++nIndex )
160 rStrm >> aColor;
161 maColorTable[ nIndex ] = aColor.GetColor();
163 ExportPalette();
166 // FONT record - font information =============================================
168 XclImpFont::XclImpFont( const XclImpRoot& rRoot ) :
169 XclImpRoot( rRoot ),
170 mbHasCharSet( false ),
171 mbHasWstrn( true ),
172 mbHasAsian( false ),
173 mbHasCmplx( false )
175 SetAllUsedFlags( false );
178 XclImpFont::XclImpFont( const XclImpRoot& rRoot, const XclFontData& rFontData ) :
179 XclImpRoot( rRoot )
181 SetFontData( rFontData, false );
184 void XclImpFont::SetAllUsedFlags( bool bUsed )
186 mbFontNameUsed = mbHeightUsed = mbColorUsed = mbWeightUsed = mbEscapemUsed =
187 mbUnderlUsed = mbItalicUsed = mbStrikeUsed = mbOutlineUsed = mbShadowUsed = bUsed;
190 void XclImpFont::SetFontData( const XclFontData& rFontData, bool bHasCharSet )
192 maData = rFontData;
193 mbHasCharSet = bHasCharSet;
194 if( maData.maStyle.Len() )
196 if( SfxObjectShell* pDocShell = GetDocShell() )
198 if( const SvxFontListItem* pInfoItem = static_cast< const SvxFontListItem* >(
199 pDocShell->GetItem( SID_ATTR_CHAR_FONTLIST ) ) )
201 if( const FontList* pFontList = pInfoItem->GetFontList() )
203 FontInfo aFontInfo( pFontList->Get( maData.maName, maData.maStyle ) );
204 maData.SetScWeight( aFontInfo.GetWeight() );
205 maData.SetScPosture( aFontInfo.GetItalic() );
209 maData.maStyle.Erase();
211 GuessScriptType();
212 SetAllUsedFlags( true );
215 rtl_TextEncoding XclImpFont::GetFontEncoding() const
217 // #i63105# use text encoding from FONT record
218 // #i67768# BIFF2-BIFF4 FONT records do not contain character set
219 rtl_TextEncoding eFontEnc = mbHasCharSet ? maData.GetFontEncoding() : GetTextEncoding();
220 return (eFontEnc == RTL_TEXTENCODING_DONTKNOW) ? GetTextEncoding() : eFontEnc;
223 void XclImpFont::ReadFont( XclImpStream& rStrm )
225 switch( GetBiff() )
227 case EXC_BIFF2:
228 ReadFontData2( rStrm );
229 ReadFontName2( rStrm );
230 break;
231 case EXC_BIFF3:
232 case EXC_BIFF4:
233 ReadFontData2( rStrm );
234 ReadFontColor( rStrm );
235 ReadFontName2( rStrm );
236 break;
237 case EXC_BIFF5:
238 ReadFontData5( rStrm );
239 ReadFontName2( rStrm );
240 break;
241 case EXC_BIFF8:
242 ReadFontData5( rStrm );
243 ReadFontName8( rStrm );
244 break;
245 default:
246 DBG_ERROR_BIFF();
247 return;
249 GuessScriptType();
250 SetAllUsedFlags( true );
253 void XclImpFont::ReadEfont( XclImpStream& rStrm )
255 ReadFontColor( rStrm );
258 void XclImpFont::ReadCFFontBlock( XclImpStream& rStrm )
260 OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
261 if( GetBiff() != EXC_BIFF8 )
262 return;
264 sal_uInt32 nHeight, nStyle, nColor, nFontFlags1, nFontFlags2, nFontFlags3;
265 sal_uInt16 nWeight, nEscapem;
266 sal_uInt8 nUnderl;
268 rStrm.Ignore( 64 );
269 rStrm >> nHeight >> nStyle >> nWeight >> nEscapem >> nUnderl;
270 rStrm.Ignore( 3 );
271 rStrm >> nColor;
272 rStrm.Ignore( 4 );
273 rStrm >> nFontFlags1 >> nFontFlags2 >> nFontFlags3;
274 rStrm.Ignore( 18 );
276 if( (mbHeightUsed = (nHeight <= 0x7FFF)) == true )
277 maData.mnHeight = static_cast< sal_uInt16 >( nHeight );
278 if( (mbWeightUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STYLE ) && (nWeight < 0x7FFF)) == true )
279 maData.mnWeight = static_cast< sal_uInt16 >( nWeight );
280 if( (mbItalicUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STYLE )) == true )
281 maData.mbItalic = ::get_flag( nStyle, EXC_CF_FONT_STYLE );
282 if( (mbUnderlUsed = !::get_flag( nFontFlags3, EXC_CF_FONT_UNDERL ) && (nUnderl <= 0x7F)) == true )
283 maData.mnUnderline = nUnderl;
284 if( (mbColorUsed = (nColor <= 0x7FFF)) == true )
285 maData.maColor = GetPalette().GetColor( static_cast< sal_uInt16 >( nColor ) );
286 if( (mbStrikeUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STRIKEOUT )) == true )
287 maData.mbStrikeout = ::get_flag( nStyle, EXC_CF_FONT_STRIKEOUT );
290 void XclImpFont::FillToItemSet( SfxItemSet& rItemSet, XclFontItemType eType, bool bSkipPoolDefs ) const
292 // true = edit engine Which-IDs (EE_CHAR_*); false = Calc Which-IDs (ATTR_*)
293 bool bEE = eType != EXC_FONTITEM_CELL;
295 // item = the item to put into the item set
296 // sc_which = the Calc Which-ID of the item
297 // ee_which = the edit engine Which-ID of the item
298 #define PUTITEM( item, sc_which, ee_which ) \
299 ScfTools::PutItem( rItemSet, item, (bEE ? (ee_which) : (sc_which)), bSkipPoolDefs )
301 // Font item
302 // #i36997# do not set default Tahoma font from notes
303 bool bDefNoteFont = (eType == EXC_FONTITEM_NOTE) && (maData.maName.EqualsIgnoreCaseAscii( "Tahoma" ));
304 if( mbFontNameUsed && !bDefNoteFont )
306 rtl_TextEncoding eFontEnc = maData.GetFontEncoding();
307 rtl_TextEncoding eTempTextEnc = (bEE && (eFontEnc == GetTextEncoding())) ?
308 ScfTools::GetSystemTextEncoding() : eFontEnc;
310 //add corresponding pitch for FontFamily
311 FontPitch ePitch = PITCH_DONTKNOW;
312 FontFamily eFtFamily = maData.GetScFamily( GetTextEncoding() );
313 switch( eFtFamily ) //refer http://msdn.microsoft.com/en-us/library/aa246306(v=VS.60).aspx
315 case FAMILY_ROMAN: ePitch = PITCH_VARIABLE; break;
316 case FAMILY_SWISS: ePitch = PITCH_VARIABLE; break;
317 case FAMILY_MODERN: ePitch = PITCH_FIXED; break;
318 default: break;
320 SvxFontItem aFontItem( eFtFamily , maData.maName, EMPTY_STRING, ePitch, eTempTextEnc, ATTR_FONT );
322 // set only for valid script types
323 if( mbHasWstrn )
324 PUTITEM( aFontItem, ATTR_FONT, EE_CHAR_FONTINFO );
325 if( mbHasAsian )
326 PUTITEM( aFontItem, ATTR_CJK_FONT, EE_CHAR_FONTINFO_CJK );
327 if( mbHasCmplx )
328 PUTITEM( aFontItem, ATTR_CTL_FONT, EE_CHAR_FONTINFO_CTL );
331 // Font height (for all script types)
332 if( mbHeightUsed )
334 sal_Int32 nHeight = maData.mnHeight;
335 if( bEE && (eType != EXC_FONTITEM_HF) ) // do not convert header/footer height
336 nHeight = (nHeight * 127 + 36) / EXC_POINTS_PER_INCH; // 1 in == 72 pt
338 SvxFontHeightItem aHeightItem( nHeight, 100, ATTR_FONT_HEIGHT );
339 PUTITEM( aHeightItem, ATTR_FONT_HEIGHT, EE_CHAR_FONTHEIGHT );
340 PUTITEM( aHeightItem, ATTR_CJK_FONT_HEIGHT, EE_CHAR_FONTHEIGHT_CJK );
341 PUTITEM( aHeightItem, ATTR_CTL_FONT_HEIGHT, EE_CHAR_FONTHEIGHT_CTL );
344 // Font color - pass AUTO_COL to item
345 if( mbColorUsed )
346 PUTITEM( SvxColorItem( maData.maColor, ATTR_FONT_COLOR ), ATTR_FONT_COLOR, EE_CHAR_COLOR );
348 // Font weight (for all script types)
349 if( mbWeightUsed )
351 SvxWeightItem aWeightItem( maData.GetScWeight(), ATTR_FONT_WEIGHT );
352 PUTITEM( aWeightItem, ATTR_FONT_WEIGHT, EE_CHAR_WEIGHT );
353 PUTITEM( aWeightItem, ATTR_CJK_FONT_WEIGHT, EE_CHAR_WEIGHT_CJK );
354 PUTITEM( aWeightItem, ATTR_CTL_FONT_WEIGHT, EE_CHAR_WEIGHT_CTL );
357 // Font underline
358 if( mbUnderlUsed )
360 SvxUnderlineItem aUnderlItem( maData.GetScUnderline(), ATTR_FONT_UNDERLINE );
361 PUTITEM( aUnderlItem, ATTR_FONT_UNDERLINE, EE_CHAR_UNDERLINE );
364 // Font posture (for all script types)
365 if( mbItalicUsed )
367 SvxPostureItem aPostItem( maData.GetScPosture(), ATTR_FONT_POSTURE );
368 PUTITEM( aPostItem, ATTR_FONT_POSTURE, EE_CHAR_ITALIC );
369 PUTITEM( aPostItem, ATTR_CJK_FONT_POSTURE, EE_CHAR_ITALIC_CJK );
370 PUTITEM( aPostItem, ATTR_CTL_FONT_POSTURE, EE_CHAR_ITALIC_CTL );
373 // Boolean attributes crossed out, contoured, shadowed
374 if( mbStrikeUsed )
375 PUTITEM( SvxCrossedOutItem( maData.GetScStrikeout(), ATTR_FONT_CROSSEDOUT ), ATTR_FONT_CROSSEDOUT, EE_CHAR_STRIKEOUT );
376 if( mbOutlineUsed )
377 PUTITEM( SvxContourItem( maData.mbOutline, ATTR_FONT_CONTOUR ), ATTR_FONT_CONTOUR, EE_CHAR_OUTLINE );
378 if( mbShadowUsed )
379 PUTITEM( SvxShadowedItem( maData.mbShadow, ATTR_FONT_SHADOWED ), ATTR_FONT_SHADOWED, EE_CHAR_SHADOW );
381 // Super-/subscript: only on edit engine objects
382 if( mbEscapemUsed && bEE )
383 rItemSet.Put( SvxEscapementItem( maData.GetScEscapement(), EE_CHAR_ESCAPEMENT ) );
385 #undef PUTITEM
388 void XclImpFont::WriteFontProperties( ScfPropertySet& rPropSet,
389 XclFontPropSetType eType, const Color* pFontColor ) const
391 GetFontPropSetHelper().WriteFontProperties(
392 rPropSet, eType, maData, mbHasWstrn, mbHasAsian, mbHasCmplx, pFontColor );
395 void XclImpFont::ReadFontData2( XclImpStream& rStrm )
397 sal_uInt16 nFlags;
398 rStrm >> maData.mnHeight >> nFlags;
400 maData.mnWeight = ::get_flagvalue( nFlags, EXC_FONTATTR_BOLD, EXC_FONTWGHT_BOLD, EXC_FONTWGHT_NORMAL );
401 maData.mnUnderline = ::get_flagvalue( nFlags, EXC_FONTATTR_UNDERLINE, EXC_FONTUNDERL_SINGLE, EXC_FONTUNDERL_NONE );
402 maData.mbItalic = ::get_flag( nFlags, EXC_FONTATTR_ITALIC );
403 maData.mbStrikeout = ::get_flag( nFlags, EXC_FONTATTR_STRIKEOUT );
404 maData.mbOutline = ::get_flag( nFlags, EXC_FONTATTR_OUTLINE );
405 maData.mbShadow = ::get_flag( nFlags, EXC_FONTATTR_SHADOW );
406 mbHasCharSet = false;
409 void XclImpFont::ReadFontData5( XclImpStream& rStrm )
411 sal_uInt16 nFlags;
413 rStrm >> maData.mnHeight >> nFlags;
414 ReadFontColor( rStrm );
415 rStrm >> maData.mnWeight >> maData.mnEscapem >> maData.mnUnderline >> maData.mnFamily >> maData.mnCharSet;
416 rStrm.Ignore( 1 );
418 maData.mbItalic = ::get_flag( nFlags, EXC_FONTATTR_ITALIC );
419 maData.mbStrikeout = ::get_flag( nFlags, EXC_FONTATTR_STRIKEOUT );
420 maData.mbOutline = ::get_flag( nFlags, EXC_FONTATTR_OUTLINE );
421 maData.mbShadow = ::get_flag( nFlags, EXC_FONTATTR_SHADOW );
422 mbHasCharSet = true;
425 void XclImpFont::ReadFontColor( XclImpStream& rStrm )
427 maData.maColor = GetPalette().GetColor( rStrm.ReaduInt16() );
430 void XclImpFont::ReadFontName2( XclImpStream& rStrm )
432 maData.maName = rStrm.ReadByteString( false );
435 void XclImpFont::ReadFontName8( XclImpStream& rStrm )
437 maData.maName = rStrm.ReadUniString( rStrm.ReaduInt8() );
440 void XclImpFont::GuessScriptType()
442 mbHasWstrn = true;
443 mbHasAsian = mbHasCmplx = false;
445 // find the script types for which the font contains characters
446 if( OutputDevice* pPrinter = GetPrinter() )
448 Font aFont( maData.maName, Size( 0, 10 ) );
449 FontCharMap aCharMap;
451 pPrinter->SetFont( aFont );
452 if( pPrinter->GetFontCharMap( aCharMap ) )
454 // CJK fonts
455 mbHasAsian =
456 aCharMap.HasChar( 0x3041 ) || // 3040-309F: Hiragana
457 aCharMap.HasChar( 0x30A1 ) || // 30A0-30FF: Katakana
458 aCharMap.HasChar( 0x3111 ) || // 3100-312F: Bopomofo
459 aCharMap.HasChar( 0x3131 ) || // 3130-318F: Hangul Compatibility Jamo
460 aCharMap.HasChar( 0x3301 ) || // 3300-33FF: CJK Compatibility
461 aCharMap.HasChar( 0x3401 ) || // 3400-4DBF: CJK Unified Ideographs Extension A
462 aCharMap.HasChar( 0x4E01 ) || // 4E00-9FAF: CJK Unified Ideographs
463 aCharMap.HasChar( 0x7E01 ) || // 4E00-9FAF: CJK unified ideographs
464 aCharMap.HasChar( 0xA001 ) || // A001-A48F: Yi Syllables
465 aCharMap.HasChar( 0xAC01 ) || // AC00-D7AF: Hangul Syllables
466 aCharMap.HasChar( 0xCC01 ) || // AC00-D7AF: Hangul Syllables
467 aCharMap.HasChar( 0xF901 ) || // F900-FAFF: CJK Compatibility Ideographs
468 aCharMap.HasChar( 0xFF71 ); // FF00-FFEF: Halfwidth/Fullwidth Forms
469 // CTL fonts
470 mbHasCmplx =
471 aCharMap.HasChar( 0x05D1 ) || // 0590-05FF: Hebrew
472 aCharMap.HasChar( 0x0631 ) || // 0600-06FF: Arabic
473 aCharMap.HasChar( 0x0721 ) || // 0700-074F: Syriac
474 aCharMap.HasChar( 0x0911 ) || // 0900-0DFF: Indic scripts
475 aCharMap.HasChar( 0x0E01 ) || // 0E00-0E7F: Thai
476 aCharMap.HasChar( 0xFB21 ) || // FB1D-FB4F: Hebrew Presentation Forms
477 aCharMap.HasChar( 0xFB51 ) || // FB50-FDFF: Arabic Presentation Forms-A
478 aCharMap.HasChar( 0xFE71 ); // FE70-FEFF: Arabic Presentation Forms-B
479 // Western fonts
480 mbHasWstrn = (!mbHasAsian && !mbHasCmplx) || aCharMap.HasChar( 'A' );
485 // ----------------------------------------------------------------------------
487 XclImpFontBuffer::XclImpFontBuffer( const XclImpRoot& rRoot ) :
488 XclImpRoot( rRoot ),
489 maFont4( rRoot ),
490 maCtrlFont( rRoot )
492 Initialize();
494 // default font for form controls without own font information
495 XclFontData aCtrlFontData;
496 switch( GetBiff() )
498 case EXC_BIFF2:
499 case EXC_BIFF3:
500 case EXC_BIFF4:
501 case EXC_BIFF5:
502 aCtrlFontData.maName.AssignAscii( "Helv" );
503 aCtrlFontData.mnHeight = 160;
504 aCtrlFontData.mnWeight = EXC_FONTWGHT_BOLD;
505 break;
506 case EXC_BIFF8:
507 aCtrlFontData.maName.AssignAscii( "Tahoma" );
508 aCtrlFontData.mnHeight = 160;
509 aCtrlFontData.mnWeight = EXC_FONTWGHT_NORMAL;
510 break;
511 default:
512 DBG_ERROR_BIFF();
514 maCtrlFont.SetFontData( aCtrlFontData, false );
517 void XclImpFontBuffer::Initialize()
519 maFontList.clear();
521 // application font for column width calculation, later filled with first font from font list
522 XclFontData aAppFontData;
523 aAppFontData.maName.AssignAscii( "Arial" );
524 aAppFontData.mnHeight = 200;
525 aAppFontData.mnWeight = EXC_FONTWGHT_NORMAL;
526 UpdateAppFont( aAppFontData, false );
529 const XclImpFont* XclImpFontBuffer::GetFont( sal_uInt16 nFontIndex ) const
531 /* Font with index 4 is not stored in an Excel file, but used e.g. by
532 BIFF5 form pushbutton objects. It is the bold default font.
533 This also means that entries above 4 are out by one in the list. */
535 if (nFontIndex == 4)
536 return &maFont4;
538 if (nFontIndex < 4)
540 // Font ID is zero-based when it's less than 4.
541 return nFontIndex >= maFontList.size() ? NULL : &maFontList[nFontIndex];
544 // Font ID is greater than 4. It is now 1-based.
545 return nFontIndex > maFontList.size() ? NULL : &maFontList[nFontIndex-1];
548 void XclImpFontBuffer::ReadFont( XclImpStream& rStrm )
550 XclImpFont* pFont = new XclImpFont( GetRoot() );
551 pFont->ReadFont( rStrm );
552 maFontList.push_back( pFont );
554 if( maFontList.size() == 1 )
556 UpdateAppFont( pFont->GetFontData(), pFont->HasCharSet() );
557 // #i71033# set text encoding from application font, if CODEPAGE is missing
558 SetAppFontEncoding( pFont->GetFontEncoding() );
562 void XclImpFontBuffer::ReadEfont( XclImpStream& rStrm )
564 if( !maFontList.empty() )
565 maFontList.back().ReadEfont( rStrm );
568 void XclImpFontBuffer::FillToItemSet(
569 SfxItemSet& rItemSet, XclFontItemType eType,
570 sal_uInt16 nFontIdx, bool bSkipPoolDefs ) const
572 if( const XclImpFont* pFont = GetFont( nFontIdx ) )
573 pFont->FillToItemSet( rItemSet, eType, bSkipPoolDefs );
576 void XclImpFontBuffer::WriteFontProperties( ScfPropertySet& rPropSet,
577 XclFontPropSetType eType, sal_uInt16 nFontIdx, const Color* pFontColor ) const
579 if( const XclImpFont* pFont = GetFont( nFontIdx ) )
580 pFont->WriteFontProperties( rPropSet, eType, pFontColor );
583 void XclImpFontBuffer::WriteDefaultCtrlFontProperties( ScfPropertySet& rPropSet ) const
585 maCtrlFont.WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL );
588 void XclImpFontBuffer::UpdateAppFont( const XclFontData& rFontData, bool bHasCharSet )
590 maAppFont = rFontData;
591 // #i3006# Calculate the width of '0' from first font and current printer.
592 SetCharWidth( maAppFont );
594 // font 4 is bold font 0
595 XclFontData aFont4Data( maAppFont );
596 aFont4Data.mnWeight = EXC_FONTWGHT_BOLD;
597 maFont4.SetFontData( aFont4Data, bHasCharSet );
600 // FORMAT record - number formats =============================================
602 XclImpNumFmtBuffer::XclImpNumFmtBuffer( const XclImpRoot& rRoot ) :
603 XclNumFmtBuffer( rRoot ),
604 XclImpRoot( rRoot ),
605 mnNextXclIdx( 0 )
609 void XclImpNumFmtBuffer::Initialize()
611 maIndexMap.clear();
612 mnNextXclIdx = 0;
613 InitializeImport(); // base class
616 void XclImpNumFmtBuffer::ReadFormat( XclImpStream& rStrm )
618 String aFormat;
619 switch( GetBiff() )
621 case EXC_BIFF2:
622 case EXC_BIFF3:
623 aFormat = rStrm.ReadByteString( false );
624 break;
626 case EXC_BIFF4:
627 rStrm.Ignore( 2 ); // in BIFF4 the index field exists, but is undefined
628 aFormat = rStrm.ReadByteString( false );
629 break;
631 case EXC_BIFF5:
632 rStrm >> mnNextXclIdx;
633 aFormat = rStrm.ReadByteString( false );
634 break;
636 case EXC_BIFF8:
637 rStrm >> mnNextXclIdx;
638 aFormat = rStrm.ReadUniString();
639 break;
641 default:
642 DBG_ERROR_BIFF();
643 return;
646 if( mnNextXclIdx < 0xFFFF )
648 InsertFormat( mnNextXclIdx, aFormat );
649 ++mnNextXclIdx;
653 void XclImpNumFmtBuffer::CreateScFormats()
655 OSL_ENSURE( maIndexMap.empty(), "XclImpNumFmtBuffer::CreateScFormats - already created" );
657 SvNumberFormatter& rFormatter = GetFormatter();
658 for( XclNumFmtMap::const_iterator aIt = GetFormatMap().begin(), aEnd = GetFormatMap().end(); aIt != aEnd; ++aIt )
660 const XclNumFmt& rNumFmt = aIt->second;
662 // insert/convert the Excel number format
663 sal_Int32 nCheckPos;
664 short nType = NUMBERFORMAT_DEFINED;
665 sal_uInt32 nKey;
666 if( rNumFmt.maFormat.Len() )
668 OUString aFormat( rNumFmt.maFormat );
669 rFormatter.PutandConvertEntry( aFormat, nCheckPos,
670 nType, nKey, LANGUAGE_ENGLISH_US, rNumFmt.meLanguage );
672 else
673 nKey = rFormatter.GetFormatIndex( rNumFmt.meOffset, rNumFmt.meLanguage );
675 // insert the resulting format key into the Excel->Calc index map
676 maIndexMap[ aIt->first ] = nKey;
680 sal_uLong XclImpNumFmtBuffer::GetScFormat( sal_uInt16 nXclNumFmt ) const
682 XclImpIndexMap::const_iterator aIt = maIndexMap.find( nXclNumFmt );
683 return (aIt != maIndexMap.end()) ? aIt->second : NUMBERFORMAT_ENTRY_NOT_FOUND;
686 void XclImpNumFmtBuffer::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nXclNumFmt, bool bSkipPoolDefs ) const
688 sal_uLong nScNumFmt = GetScFormat( nXclNumFmt );
689 if( nScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND )
690 nScNumFmt = GetStdScNumFmt();
691 FillScFmtToItemSet( rItemSet, nScNumFmt, bSkipPoolDefs );
694 void XclImpNumFmtBuffer::FillScFmtToItemSet( SfxItemSet& rItemSet, sal_uLong nScNumFmt, bool bSkipPoolDefs ) const
696 OSL_ENSURE( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND, "XclImpNumFmtBuffer::FillScFmtToItemSet - invalid number format" );
697 ScfTools::PutItem( rItemSet, SfxUInt32Item( ATTR_VALUE_FORMAT, nScNumFmt ), bSkipPoolDefs );
698 if( rItemSet.GetItemState( ATTR_VALUE_FORMAT, false ) == SFX_ITEM_SET )
699 ScGlobal::AddLanguage( rItemSet, GetFormatter() );
702 // XF, STYLE record - Cell formatting =========================================
704 void XclImpCellProt::FillFromXF2( sal_uInt8 nNumFmt )
706 mbLocked = ::get_flag( nNumFmt, EXC_XF2_LOCKED );
707 mbHidden = ::get_flag( nNumFmt, EXC_XF2_HIDDEN );
710 void XclImpCellProt::FillFromXF3( sal_uInt16 nProt )
712 mbLocked = ::get_flag( nProt, EXC_XF_LOCKED );
713 mbHidden = ::get_flag( nProt, EXC_XF_HIDDEN );
716 void XclImpCellProt::FillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
718 ScfTools::PutItem( rItemSet, ScProtectionAttr( mbLocked, mbHidden ), bSkipPoolDefs );
722 // ----------------------------------------------------------------------------
724 void XclImpCellAlign::FillFromXF2( sal_uInt8 nFlags )
726 mnHorAlign = ::extract_value< sal_uInt8 >( nFlags, 0, 3 );
729 void XclImpCellAlign::FillFromXF3( sal_uInt16 nAlign )
731 mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
732 mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK ); // new in BIFF3
735 void XclImpCellAlign::FillFromXF4( sal_uInt16 nAlign )
737 FillFromXF3( nAlign );
738 mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 2 ); // new in BIFF4
739 mnOrient = ::extract_value< sal_uInt8 >( nAlign, 6, 2 ); // new in BIFF4
742 void XclImpCellAlign::FillFromXF5( sal_uInt16 nAlign )
744 mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
745 mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 3 );
746 mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK );
747 mnOrient = ::extract_value< sal_uInt8 >( nAlign, 8, 2 );
750 void XclImpCellAlign::FillFromXF8( sal_uInt16 nAlign, sal_uInt16 nMiscAttrib )
752 mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
753 mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 3 );
754 mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK );
755 mnRotation = ::extract_value< sal_uInt8 >( nAlign, 8, 8 ); // new in BIFF8
756 mnIndent = ::extract_value< sal_uInt8 >( nMiscAttrib, 0, 4 ); // new in BIFF8
757 mbShrink = ::get_flag( nMiscAttrib, EXC_XF8_SHRINK ); // new in BIFF8
758 mnTextDir = ::extract_value< sal_uInt8 >( nMiscAttrib, 6, 2 ); // new in BIFF8
761 void XclImpCellAlign::FillToItemSet( SfxItemSet& rItemSet, const XclImpFont* pFont, bool bSkipPoolDefs ) const
763 // horizontal alignment
764 ScfTools::PutItem( rItemSet, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY ), bSkipPoolDefs );
765 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( GetScHorJustifyMethod(), ATTR_HOR_JUSTIFY_METHOD ), bSkipPoolDefs );
767 // text wrap (#i74508# always if vertical alignment is justified or distributed)
768 bool bLineBreak = mbLineBreak || (mnVerAlign == EXC_XF_VER_JUSTIFY) || (mnVerAlign == EXC_XF_VER_DISTRIB);
769 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_LINEBREAK, bLineBreak ), bSkipPoolDefs );
771 // vertical alignment
772 ScfTools::PutItem( rItemSet, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY ), bSkipPoolDefs );
773 ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( GetScVerJustifyMethod(), ATTR_VER_JUSTIFY_METHOD ), bSkipPoolDefs );
775 // indent
776 sal_uInt16 nScIndent = mnIndent * 200; // 1 Excel unit == 10 pt == 200 twips
777 ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_INDENT, nScIndent ), bSkipPoolDefs );
779 // shrink to fit
780 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_SHRINKTOFIT, mbShrink ), bSkipPoolDefs );
782 // text orientation/rotation (BIFF2-BIFF7 sets mnOrient)
783 sal_uInt8 nXclRot = (mnOrient == EXC_ORIENT_NONE) ? mnRotation : XclTools::GetXclRotFromOrient( mnOrient );
784 bool bStacked = (nXclRot == EXC_ROT_STACKED);
785 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_STACKED, bStacked ), bSkipPoolDefs );
786 // set an angle in the range from -90 to 90 degrees
787 sal_Int32 nAngle = XclTools::GetScRotation( nXclRot, 0 );
788 ScfTools::PutItem( rItemSet, SfxInt32Item( ATTR_ROTATE_VALUE, nAngle ), bSkipPoolDefs );
789 // set "Use asian vertical layout", if cell is stacked and font contains CKJ characters
790 bool bAsianVert = bStacked && pFont && pFont->HasAsianChars();
791 ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_VERTICAL_ASIAN, bAsianVert ), bSkipPoolDefs );
793 // CTL text direction
794 ScfTools::PutItem( rItemSet, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR ), bSkipPoolDefs );
797 // ----------------------------------------------------------------------------
799 XclImpCellBorder::XclImpCellBorder()
801 SetUsedFlags( false, false );
804 void XclImpCellBorder::SetUsedFlags( bool bOuterUsed, bool bDiagUsed )
806 mbLeftUsed = mbRightUsed = mbTopUsed = mbBottomUsed = bOuterUsed;
807 mbDiagUsed = bDiagUsed;
810 void XclImpCellBorder::FillFromXF2( sal_uInt8 nFlags )
812 mnLeftLine = ::get_flagvalue( nFlags, EXC_XF2_LEFTLINE, EXC_LINE_THIN, EXC_LINE_NONE );
813 mnRightLine = ::get_flagvalue( nFlags, EXC_XF2_RIGHTLINE, EXC_LINE_THIN, EXC_LINE_NONE );
814 mnTopLine = ::get_flagvalue( nFlags, EXC_XF2_TOPLINE, EXC_LINE_THIN, EXC_LINE_NONE );
815 mnBottomLine = ::get_flagvalue( nFlags, EXC_XF2_BOTTOMLINE, EXC_LINE_THIN, EXC_LINE_NONE );
816 mnLeftColor = mnRightColor = mnTopColor = mnBottomColor = EXC_COLOR_BIFF2_BLACK;
817 SetUsedFlags( true, false );
820 void XclImpCellBorder::FillFromXF3( sal_uInt32 nBorder )
822 mnTopLine = ::extract_value< sal_uInt8 >( nBorder, 0, 3 );
823 mnLeftLine = ::extract_value< sal_uInt8 >( nBorder, 8, 3 );
824 mnBottomLine = ::extract_value< sal_uInt8 >( nBorder, 16, 3 );
825 mnRightLine = ::extract_value< sal_uInt8 >( nBorder, 24, 3 );
826 mnTopColor = ::extract_value< sal_uInt16 >( nBorder, 3, 5 );
827 mnLeftColor = ::extract_value< sal_uInt16 >( nBorder, 11, 5 );
828 mnBottomColor = ::extract_value< sal_uInt16 >( nBorder, 19, 5 );
829 mnRightColor = ::extract_value< sal_uInt16 >( nBorder, 27, 5 );
830 SetUsedFlags( true, false );
833 void XclImpCellBorder::FillFromXF5( sal_uInt32 nBorder, sal_uInt32 nArea )
835 mnTopLine = ::extract_value< sal_uInt8 >( nBorder, 0, 3 );
836 mnLeftLine = ::extract_value< sal_uInt8 >( nBorder, 3, 3 );
837 mnBottomLine = ::extract_value< sal_uInt8 >( nArea, 22, 3 );
838 mnRightLine = ::extract_value< sal_uInt8 >( nBorder, 6, 3 );
839 mnTopColor = ::extract_value< sal_uInt16 >( nBorder, 9, 7 );
840 mnLeftColor = ::extract_value< sal_uInt16 >( nBorder, 16, 7 );
841 mnBottomColor = ::extract_value< sal_uInt16 >( nArea, 25, 7 );
842 mnRightColor = ::extract_value< sal_uInt16 >( nBorder, 23, 7 );
843 SetUsedFlags( true, false );
846 void XclImpCellBorder::FillFromXF8( sal_uInt32 nBorder1, sal_uInt32 nBorder2 )
848 mnLeftLine = ::extract_value< sal_uInt8 >( nBorder1, 0, 4 );
849 mnRightLine = ::extract_value< sal_uInt8 >( nBorder1, 4, 4 );
850 mnTopLine = ::extract_value< sal_uInt8 >( nBorder1, 8, 4 );
851 mnBottomLine = ::extract_value< sal_uInt8 >( nBorder1, 12, 4 );
852 mnLeftColor = ::extract_value< sal_uInt16 >( nBorder1, 16, 7 );
853 mnRightColor = ::extract_value< sal_uInt16 >( nBorder1, 23, 7 );
854 mnTopColor = ::extract_value< sal_uInt16 >( nBorder2, 0, 7 );
855 mnBottomColor = ::extract_value< sal_uInt16 >( nBorder2, 7, 7 );
856 mbDiagTLtoBR = ::get_flag( nBorder1, EXC_XF_DIAGONAL_TL_TO_BR );
857 mbDiagBLtoTR = ::get_flag( nBorder1, EXC_XF_DIAGONAL_BL_TO_TR );
858 if( mbDiagTLtoBR || mbDiagBLtoTR )
860 mnDiagLine = ::extract_value< sal_uInt8 >( nBorder2, 21, 4 );
861 mnDiagColor = ::extract_value< sal_uInt16 >( nBorder2, 14, 7 );
863 SetUsedFlags( true, true );
866 void XclImpCellBorder::FillFromCF8( sal_uInt16 nLineStyle, sal_uInt32 nLineColor, sal_uInt32 nFlags )
868 mnLeftLine = ::extract_value< sal_uInt8 >( nLineStyle, 0, 4 );
869 mnRightLine = ::extract_value< sal_uInt8 >( nLineStyle, 4, 4 );
870 mnTopLine = ::extract_value< sal_uInt8 >( nLineStyle, 8, 4 );
871 mnBottomLine = ::extract_value< sal_uInt8 >( nLineStyle, 12, 4 );
872 mnLeftColor = ::extract_value< sal_uInt16 >( nLineColor, 0, 7 );
873 mnRightColor = ::extract_value< sal_uInt16 >( nLineColor, 7, 7 );
874 mnTopColor = ::extract_value< sal_uInt16 >( nLineColor, 16, 7 );
875 mnBottomColor = ::extract_value< sal_uInt16 >( nLineColor, 23, 7 );
876 mbLeftUsed = !::get_flag( nFlags, EXC_CF_BORDER_LEFT );
877 mbRightUsed = !::get_flag( nFlags, EXC_CF_BORDER_RIGHT );
878 mbTopUsed = !::get_flag( nFlags, EXC_CF_BORDER_TOP );
879 mbBottomUsed = !::get_flag( nFlags, EXC_CF_BORDER_BOTTOM );
880 mbDiagUsed = false;
883 bool XclImpCellBorder::HasAnyOuterBorder() const
885 return
886 (mbLeftUsed && (mnLeftLine != EXC_LINE_NONE)) ||
887 (mbRightUsed && (mnRightLine != EXC_LINE_NONE)) ||
888 (mbTopUsed && (mnTopLine != EXC_LINE_NONE)) ||
889 (mbBottomUsed && (mnBottomLine != EXC_LINE_NONE));
892 namespace {
894 /** Converts the passed line style to a ::editeng::SvxBorderLine, or returns false, if style is "no line". */
895 bool lclConvertBorderLine( ::editeng::SvxBorderLine& rLine, const XclImpPalette& rPalette, sal_uInt8 nXclLine, sal_uInt16 nXclColor )
897 static const sal_uInt16 ppnLineParam[][ 4 ] =
899 // outer width, type
900 { 0, table::BorderLineStyle::SOLID }, // 0 = none
901 { EXC_BORDER_THIN, table::BorderLineStyle::SOLID }, // 1 = thin
902 { EXC_BORDER_MEDIUM, table::BorderLineStyle::SOLID }, // 2 = medium
903 { EXC_BORDER_THIN, table::BorderLineStyle::DASHED }, // 3 = dashed
904 { EXC_BORDER_THIN, table::BorderLineStyle::DOTTED }, // 4 = dotted
905 { EXC_BORDER_THICK, table::BorderLineStyle::SOLID }, // 5 = thick
906 { EXC_BORDER_THIN, table::BorderLineStyle::DOUBLE }, // 6 = double
907 { EXC_BORDER_HAIR, table::BorderLineStyle::FINE_DASHED }, // 7 = hair
908 { EXC_BORDER_MEDIUM, table::BorderLineStyle::DASHED }, // 8 = med dash
909 { EXC_BORDER_THIN, table::BorderLineStyle::SOLID }, // 9 = thin dashdot
910 { EXC_BORDER_MEDIUM, table::BorderLineStyle::SOLID }, // A = med dashdot
911 { EXC_BORDER_THIN, table::BorderLineStyle::SOLID }, // B = thin dashdotdot
912 { EXC_BORDER_MEDIUM, table::BorderLineStyle::SOLID }, // C = med dashdotdot
913 { EXC_BORDER_MEDIUM, table::BorderLineStyle::SOLID } // D = med slant dashdot
916 if( nXclLine == EXC_LINE_NONE )
917 return false;
918 if( nXclLine >= SAL_N_ELEMENTS( ppnLineParam ) )
919 nXclLine = EXC_LINE_THIN;
921 rLine.SetColor( rPalette.GetColor( nXclColor ) );
922 rLine.SetWidth( ppnLineParam[ nXclLine ][ 0 ] );
923 rLine.SetBorderLineStyle( static_cast< ::editeng::SvxBorderStyle>(
924 ppnLineParam[ nXclLine ][ 1 ]) );
925 return true;
928 } // namespace
930 void XclImpCellBorder::FillToItemSet( SfxItemSet& rItemSet, const XclImpPalette& rPalette, bool bSkipPoolDefs ) const
932 if( mbLeftUsed || mbRightUsed || mbTopUsed || mbBottomUsed )
934 SvxBoxItem aBoxItem( ATTR_BORDER );
935 ::editeng::SvxBorderLine aLine;
936 if( mbLeftUsed && lclConvertBorderLine( aLine, rPalette, mnLeftLine, mnLeftColor ) )
937 aBoxItem.SetLine( &aLine, BOX_LINE_LEFT );
938 if( mbRightUsed && lclConvertBorderLine( aLine, rPalette, mnRightLine, mnRightColor ) )
939 aBoxItem.SetLine( &aLine, BOX_LINE_RIGHT );
940 if( mbTopUsed && lclConvertBorderLine( aLine, rPalette, mnTopLine, mnTopColor ) )
941 aBoxItem.SetLine( &aLine, BOX_LINE_TOP );
942 if( mbBottomUsed && lclConvertBorderLine( aLine, rPalette, mnBottomLine, mnBottomColor ) )
943 aBoxItem.SetLine( &aLine, BOX_LINE_BOTTOM );
944 ScfTools::PutItem( rItemSet, aBoxItem, bSkipPoolDefs );
946 if( mbDiagUsed )
948 SvxLineItem aTLBRItem( ATTR_BORDER_TLBR );
949 SvxLineItem aBLTRItem( ATTR_BORDER_BLTR );
950 ::editeng::SvxBorderLine aLine;
951 if( lclConvertBorderLine( aLine, rPalette, mnDiagLine, mnDiagColor ) )
953 if( mbDiagTLtoBR )
954 aTLBRItem.SetLine( &aLine );
955 if( mbDiagBLtoTR )
956 aBLTRItem.SetLine( &aLine );
958 ScfTools::PutItem( rItemSet, aTLBRItem, bSkipPoolDefs );
959 ScfTools::PutItem( rItemSet, aBLTRItem, bSkipPoolDefs );
963 // ----------------------------------------------------------------------------
965 XclImpCellArea::XclImpCellArea()
967 SetUsedFlags( false );
970 void XclImpCellArea::SetUsedFlags( bool bUsed )
972 mbForeUsed = mbBackUsed = mbPattUsed = bUsed;
975 void XclImpCellArea::FillFromXF2( sal_uInt8 nFlags )
977 mnPattern = ::get_flagvalue( nFlags, EXC_XF2_BACKGROUND, EXC_PATT_12_5_PERC, EXC_PATT_NONE );
978 mnForeColor = EXC_COLOR_BIFF2_BLACK;
979 mnBackColor = EXC_COLOR_BIFF2_WHITE;
980 SetUsedFlags( true );
983 void XclImpCellArea::FillFromXF3( sal_uInt16 nArea )
985 mnPattern = ::extract_value< sal_uInt8 >( nArea, 0, 6 );
986 mnForeColor = ::extract_value< sal_uInt16 >( nArea, 6, 5 );
987 mnBackColor = ::extract_value< sal_uInt16 >( nArea, 11, 5 );
988 SetUsedFlags( true );
991 void XclImpCellArea::FillFromXF5( sal_uInt32 nArea )
993 mnPattern = ::extract_value< sal_uInt8 >( nArea, 16, 6 );
994 mnForeColor = ::extract_value< sal_uInt16 >( nArea, 0, 7 );
995 mnBackColor = ::extract_value< sal_uInt16 >( nArea, 7, 7 );
996 SetUsedFlags( true );
999 void XclImpCellArea::FillFromXF8( sal_uInt32 nBorder2, sal_uInt16 nArea )
1001 mnPattern = ::extract_value< sal_uInt8 >( nBorder2, 26, 6 );
1002 mnForeColor = ::extract_value< sal_uInt16 >( nArea, 0, 7 );
1003 mnBackColor = ::extract_value< sal_uInt16 >( nArea, 7, 7 );
1004 SetUsedFlags( true );
1007 void XclImpCellArea::FillFromCF8( sal_uInt16 nPattern, sal_uInt16 nColor, sal_uInt32 nFlags )
1009 mnForeColor = ::extract_value< sal_uInt16 >( nColor, 0, 7 );
1010 mnBackColor = ::extract_value< sal_uInt16 >( nColor, 7, 7 );
1011 mnPattern = ::extract_value< sal_uInt8 >( nPattern, 10, 6 );
1012 mbForeUsed = !::get_flag( nFlags, EXC_CF_AREA_FGCOLOR );
1013 mbBackUsed = !::get_flag( nFlags, EXC_CF_AREA_BGCOLOR );
1014 mbPattUsed = !::get_flag( nFlags, EXC_CF_AREA_PATTERN );
1016 if( mbBackUsed && (!mbPattUsed || (mnPattern == EXC_PATT_SOLID)) )
1018 mnForeColor = mnBackColor;
1019 mnPattern = EXC_PATT_SOLID;
1020 mbForeUsed = mbPattUsed = true;
1022 else if( !mbBackUsed && mbPattUsed && (mnPattern == EXC_PATT_SOLID) )
1024 mbPattUsed = false;
1028 void XclImpCellArea::FillToItemSet( SfxItemSet& rItemSet, const XclImpPalette& rPalette, bool bSkipPoolDefs ) const
1030 if( mbPattUsed ) // colors may be both unused in cond. formats
1032 SvxBrushItem aBrushItem( ATTR_BACKGROUND );
1034 // do not use IsTransparent() - old Calc filter writes tranparency with different color indexes
1035 if( mnPattern == EXC_PATT_NONE )
1037 aBrushItem.SetColor( Color( COL_TRANSPARENT ) );
1039 else
1041 Color aFore( rPalette.GetColor( mbForeUsed ? mnForeColor : EXC_COLOR_WINDOWTEXT ) );
1042 Color aBack( rPalette.GetColor( mbBackUsed ? mnBackColor : EXC_COLOR_WINDOWBACK ) );
1043 aBrushItem.SetColor( XclTools::GetPatternColor( aFore, aBack, mnPattern ) );
1046 ScfTools::PutItem( rItemSet, aBrushItem, bSkipPoolDefs );
1051 // ----------------------------------------------------------------------------
1053 XclImpXF::XclImpXF( const XclImpRoot& rRoot ) :
1054 XclXFBase( true ), // default is cell XF
1055 XclImpRoot( rRoot ),
1056 mpStyleSheet( 0 ),
1057 mnXclNumFmt( 0 ),
1058 mnXclFont( 0 )
1062 XclImpXF::~XclImpXF()
1066 void XclImpXF::ReadXF2( XclImpStream& rStrm )
1068 sal_uInt8 nReadFont, nReadNumFmt, nFlags;
1069 rStrm >> nReadFont;
1070 rStrm.Ignore( 1 );
1071 rStrm >> nReadNumFmt >> nFlags;
1073 // XF type always cell, no parent, used flags always true
1074 SetAllUsedFlags( true );
1076 // attributes
1077 maProtection.FillFromXF2( nReadNumFmt );
1078 mnXclFont = nReadFont;
1079 mnXclNumFmt = nReadNumFmt & EXC_XF2_VALFMT_MASK;
1080 maAlignment.FillFromXF2( nFlags );
1081 maBorder.FillFromXF2( nFlags );
1082 maArea.FillFromXF2( nFlags );
1085 void XclImpXF::ReadXF3( XclImpStream& rStrm )
1087 sal_uInt32 nBorder;
1088 sal_uInt16 nTypeProt, nAlign, nArea;
1089 sal_uInt8 nReadFont, nReadNumFmt;
1090 rStrm >> nReadFont >> nReadNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1092 // XF type/parent, attribute used flags
1093 mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE ); // new in BIFF3
1094 mnParent = ::extract_value< sal_uInt16 >( nAlign, 4, 12 ); // new in BIFF3
1095 SetUsedFlags( ::extract_value< sal_uInt8 >( nTypeProt, 10, 6 ) );
1097 // attributes
1098 maProtection.FillFromXF3( nTypeProt );
1099 mnXclFont = nReadFont;
1100 mnXclNumFmt = nReadNumFmt;
1101 maAlignment.FillFromXF3( nAlign );
1102 maBorder.FillFromXF3( nBorder );
1103 maArea.FillFromXF3( nArea ); // new in BIFF3
1106 void XclImpXF::ReadXF4( XclImpStream& rStrm )
1108 sal_uInt32 nBorder;
1109 sal_uInt16 nTypeProt, nAlign, nArea;
1110 sal_uInt8 nReadFont, nReadNumFmt;
1111 rStrm >> nReadFont >> nReadNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1113 // XF type/parent, attribute used flags
1114 mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1115 mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1116 SetUsedFlags( ::extract_value< sal_uInt8 >( nAlign, 10, 6 ) );
1118 // attributes
1119 maProtection.FillFromXF3( nTypeProt );
1120 mnXclFont = nReadFont;
1121 mnXclNumFmt = nReadNumFmt;
1122 maAlignment.FillFromXF4( nAlign );
1123 maBorder.FillFromXF3( nBorder );
1124 maArea.FillFromXF3( nArea );
1127 void XclImpXF::ReadXF5( XclImpStream& rStrm )
1129 sal_uInt32 nArea, nBorder;
1130 sal_uInt16 nTypeProt, nAlign;
1131 rStrm >> mnXclFont >> mnXclNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1133 // XF type/parent, attribute used flags
1134 mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1135 mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1136 SetUsedFlags( ::extract_value< sal_uInt8 >( nAlign, 10, 6 ) );
1138 // attributes
1139 maProtection.FillFromXF3( nTypeProt );
1140 maAlignment.FillFromXF5( nAlign );
1141 maBorder.FillFromXF5( nBorder, nArea );
1142 maArea.FillFromXF5( nArea );
1145 void XclImpXF::ReadXF8( XclImpStream& rStrm )
1147 sal_uInt32 nBorder1, nBorder2;
1148 sal_uInt16 nTypeProt, nAlign, nMiscAttrib, nArea;
1149 rStrm >> mnXclFont >> mnXclNumFmt >> nTypeProt >> nAlign >> nMiscAttrib >> nBorder1 >> nBorder2 >> nArea;
1151 // XF type/parent, attribute used flags
1152 mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1153 mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1154 SetUsedFlags( ::extract_value< sal_uInt8 >( nMiscAttrib, 10, 6 ) );
1156 // attributes
1157 maProtection.FillFromXF3( nTypeProt );
1158 maAlignment.FillFromXF8( nAlign, nMiscAttrib );
1159 maBorder.FillFromXF8( nBorder1, nBorder2 );
1160 maArea.FillFromXF8( nBorder2, nArea );
1163 void XclImpXF::ReadXF( XclImpStream& rStrm )
1165 switch( GetBiff() )
1167 case EXC_BIFF2: ReadXF2( rStrm ); break;
1168 case EXC_BIFF3: ReadXF3( rStrm ); break;
1169 case EXC_BIFF4: ReadXF4( rStrm ); break;
1170 case EXC_BIFF5: ReadXF5( rStrm ); break;
1171 case EXC_BIFF8: ReadXF8( rStrm ); break;
1172 default: DBG_ERROR_BIFF();
1176 const ScPatternAttr& XclImpXF::CreatePattern( bool bSkipPoolDefs )
1178 if( mpPattern.get() )
1179 return *mpPattern;
1181 // create new pattern attribute set
1182 mpPattern.reset( new ScPatternAttr( GetDoc().GetPool() ) );
1183 SfxItemSet& rItemSet = mpPattern->GetItemSet();
1184 XclImpXF* pParentXF = IsCellXF() ? GetXFBuffer().GetXF( mnParent ) : 0;
1186 // parent cell style
1187 if( IsCellXF() && !mpStyleSheet )
1189 mpStyleSheet = GetXFBuffer().CreateStyleSheet( mnParent );
1191 /* Enables mb***Used flags, if the formatting attributes differ from
1192 the passed XF record. In cell XFs Excel uses the cell attributes,
1193 if they differ from the parent style XF.
1194 ...or if the respective flag is not set in parent style XF. */
1195 if( pParentXF )
1197 if( !mbProtUsed )
1198 mbProtUsed = !pParentXF->mbProtUsed || !(maProtection == pParentXF->maProtection);
1199 if( !mbFontUsed )
1200 mbFontUsed = !pParentXF->mbFontUsed || (mnXclFont != pParentXF->mnXclFont);
1201 if( !mbFmtUsed )
1202 mbFmtUsed = !pParentXF->mbFmtUsed || (mnXclNumFmt != pParentXF->mnXclNumFmt);
1203 if( !mbAlignUsed )
1204 mbAlignUsed = !pParentXF->mbAlignUsed || !(maAlignment == pParentXF->maAlignment);
1205 if( !mbBorderUsed )
1206 mbBorderUsed = !pParentXF->mbBorderUsed || !(maBorder == pParentXF->maBorder);
1207 if( !mbAreaUsed )
1208 mbAreaUsed = !pParentXF->mbAreaUsed || !(maArea == pParentXF->maArea);
1212 // cell protection
1213 if( mbProtUsed )
1214 maProtection.FillToItemSet( rItemSet, bSkipPoolDefs );
1216 // font
1217 if( mbFontUsed )
1218 GetFontBuffer().FillToItemSet( rItemSet, EXC_FONTITEM_CELL, mnXclFont, bSkipPoolDefs );
1220 // value format
1221 if( mbFmtUsed )
1223 GetNumFmtBuffer().FillToItemSet( rItemSet, mnXclNumFmt, bSkipPoolDefs );
1224 // Trace occurrences of Windows date formats
1225 GetTracer().TraceDates( mnXclNumFmt );
1228 // alignment
1229 if( mbAlignUsed )
1230 maAlignment.FillToItemSet( rItemSet, GetFontBuffer().GetFont( mnXclFont ), bSkipPoolDefs );
1232 // border
1233 if( mbBorderUsed )
1235 maBorder.FillToItemSet( rItemSet, GetPalette(), bSkipPoolDefs );
1236 GetTracer().TraceBorderLineStyle(maBorder.mnLeftLine > EXC_LINE_HAIR ||
1237 maBorder.mnRightLine > EXC_LINE_HAIR || maBorder.mnTopLine > EXC_LINE_HAIR ||
1238 maBorder.mnBottomLine > EXC_LINE_HAIR );
1241 // area
1242 if( mbAreaUsed )
1244 maArea.FillToItemSet( rItemSet, GetPalette(), bSkipPoolDefs );
1245 GetTracer().TraceFillPattern(maArea.mnPattern != EXC_PATT_NONE &&
1246 maArea.mnPattern != EXC_PATT_SOLID);
1249 /* #i38709# Decide which rotation reference mode to use. If any outer
1250 border line of the cell is set (either explicitly or via cell style),
1251 and the cell contents are rotated, set rotation reference to bottom of
1252 cell. This causes the borders to be painted rotated with the text. */
1253 if( mbAlignUsed || mbBorderUsed )
1255 SvxRotateMode eRotateMode = SVX_ROTATE_MODE_STANDARD;
1256 const XclImpCellAlign* pAlign = mbAlignUsed ? &maAlignment : (pParentXF ? &pParentXF->maAlignment : 0);
1257 const XclImpCellBorder* pBorder = mbBorderUsed ? &maBorder : (pParentXF ? &pParentXF->maBorder : 0);
1258 if( pAlign && pBorder && (0 < pAlign->mnRotation) && (pAlign->mnRotation <= 180) && pBorder->HasAnyOuterBorder() )
1259 eRotateMode = SVX_ROTATE_MODE_BOTTOM;
1260 ScfTools::PutItem( rItemSet, SvxRotateModeItem( eRotateMode, ATTR_ROTATE_MODE ), bSkipPoolDefs );
1263 // Excel's cell margins are different from Calc's default margins.
1264 SvxMarginItem aItem(40, 40, 40, 40, ATTR_MARGIN);
1265 ScfTools::PutItem(rItemSet, aItem, bSkipPoolDefs);
1267 return *mpPattern;
1270 void XclImpXF::ApplyPatternToAttrList(
1271 list<ScAttrEntry>& rAttrs, SCROW nRow1, SCROW nRow2, sal_uInt32 nForceScNumFmt)
1273 // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1274 CreatePattern();
1275 ScPatternAttr& rPat = *mpPattern;
1277 // insert into document
1278 ScDocument& rDoc = GetDoc();
1280 if (IsCellXF())
1282 if (mpStyleSheet)
1284 // Apply style sheet. Don't clear the direct formats.
1285 rPat.SetStyleSheet(mpStyleSheet, false);
1287 else
1289 // When the cell format is not associated with any style, use the
1290 // 'Default' style. Some buggy XLS docs generated by apps other
1291 // than Excel (such as 1C) may not have any built-in styles at
1292 // all.
1293 ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
1294 if (pStylePool)
1296 ScStyleSheet* pStyleSheet = static_cast<ScStyleSheet*>(
1297 pStylePool->Find(
1298 ScGlobal::GetRscString(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PARA));
1300 if (pStyleSheet)
1301 rPat.SetStyleSheet(pStyleSheet, false);
1307 if (nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND)
1309 ScPatternAttr aNumPat(rDoc.GetPool());
1310 GetNumFmtBuffer().FillScFmtToItemSet(aNumPat.GetItemSet(), nForceScNumFmt);
1311 rPat.GetItemSet().Put(aNumPat.GetItemSet());
1314 // Make sure we skip unnamed styles.
1315 if (rPat.GetStyleName())
1317 // Check for a gap between the last entry and this one.
1318 bool bHasGap = false;
1319 if (rAttrs.empty() && nRow1 > 0)
1320 // First attribute range doesn't start at row 0.
1321 bHasGap = true;
1323 if (!rAttrs.empty() && rAttrs.back().nRow + 1 < nRow1)
1324 bHasGap = true;
1326 if (bHasGap)
1328 // Fill this gap with the default pattern.
1329 ScAttrEntry aEntry;
1330 aEntry.nRow = nRow1 - 1;
1331 aEntry.pPattern = rDoc.GetDefPattern();
1332 rAttrs.push_back(aEntry);
1335 ScAttrEntry aEntry;
1336 aEntry.nRow = nRow2;
1337 aEntry.pPattern = static_cast<const ScPatternAttr*>(&rDoc.GetPool()->Put(rPat));
1338 rAttrs.push_back(aEntry);
1342 void XclImpXF::ApplyPattern(
1343 SCCOL nScCol1, SCROW nScRow1, SCCOL nScCol2, SCROW nScRow2,
1344 SCTAB nScTab, sal_uLong nForceScNumFmt )
1346 // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1347 const ScPatternAttr& rPattern = CreatePattern();
1349 // insert into document
1350 ScDocument& rDoc = GetDoc();
1351 if( IsCellXF() && mpStyleSheet )
1352 rDoc.ApplyStyleAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, *mpStyleSheet );
1353 if( HasUsedFlags() )
1354 rDoc.ApplyPatternAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, rPattern );
1356 // #108770# apply special number format
1357 if( nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
1359 ScPatternAttr aPattern( GetDoc().GetPool() );
1360 GetNumFmtBuffer().FillScFmtToItemSet( aPattern.GetItemSet(), nForceScNumFmt );
1361 rDoc.ApplyPatternAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, aPattern );
1365 /*static*/ void XclImpXF::ApplyPatternForBiff2CellFormat( const XclImpRoot& rRoot,
1366 const ScAddress& rScPos, sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 )
1368 /* Create an XF object and let it do the work. We will have access to its
1369 private members here. */
1370 XclImpXF aXF( rRoot );
1372 // no used flags available in BIFF2 (always true)
1373 aXF.SetAllUsedFlags( true );
1375 // set the attributes
1376 aXF.maProtection.FillFromXF2( nFlags1 );
1377 aXF.maAlignment.FillFromXF2( nFlags3 );
1378 aXF.maBorder.FillFromXF2( nFlags3 );
1379 aXF.maArea.FillFromXF2( nFlags3 );
1380 aXF.mnXclNumFmt = ::extract_value< sal_uInt16 >( nFlags2, 0, 6 );
1381 aXF.mnXclFont = ::extract_value< sal_uInt16 >( nFlags2, 6, 2 );
1383 // write the attributes to the cell
1384 aXF.ApplyPattern( rScPos.Col(), rScPos.Row(), rScPos.Col(), rScPos.Row(), rScPos.Tab() );
1387 void XclImpXF::SetUsedFlags( sal_uInt8 nUsedFlags )
1389 /* Notes about finding the mb***Used flags:
1390 - In cell XFs a *set* bit means a used attribute.
1391 - In style XFs a *cleared* bit means a used attribute.
1392 The mb***Used members always store true, if the attribute is used.
1393 The "mbCellXF == ::get_flag(...)" construct evaluates to true in
1394 both mentioned cases: cell XF and set bit; or style XF and cleared bit.
1396 mbProtUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_PROT ));
1397 mbFontUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_FONT ));
1398 mbFmtUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_VALFMT ));
1399 mbAlignUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_ALIGN ));
1400 mbBorderUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_BORDER ));
1401 mbAreaUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_AREA ));
1404 // ----------------------------------------------------------------------------
1406 XclImpStyle::XclImpStyle( const XclImpRoot& rRoot ) :
1407 XclImpRoot( rRoot ),
1408 mnXfId( EXC_XF_NOTFOUND ),
1409 mnBuiltinId( EXC_STYLE_USERDEF ),
1410 mnLevel( EXC_STYLE_NOLEVEL ),
1411 mbBuiltin( false ),
1412 mbCustom( false ),
1413 mbHidden( false ),
1414 mpStyleSheet( 0 )
1418 void XclImpStyle::ReadStyle( XclImpStream& rStrm )
1420 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF3 );
1422 sal_uInt16 nXFIndex;
1423 rStrm >> nXFIndex;
1424 mnXfId = nXFIndex & EXC_STYLE_XFMASK;
1425 mbBuiltin = ::get_flag( nXFIndex, EXC_STYLE_BUILTIN );
1427 if( mbBuiltin )
1429 rStrm >> mnBuiltinId >> mnLevel;
1431 else
1433 maName = (GetBiff() <= EXC_BIFF5) ? rStrm.ReadByteString( false ) : rStrm.ReadUniString();
1434 // #i103281# check if this is a new built-in style introduced in XL2007
1435 if( (GetBiff() == EXC_BIFF8) && (rStrm.GetNextRecId() == EXC_ID_STYLEEXT) && rStrm.StartNextRecord() )
1437 sal_uInt8 nExtFlags;
1438 rStrm.Ignore( 12 );
1439 rStrm >> nExtFlags;
1440 mbBuiltin = ::get_flag( nExtFlags, EXC_STYLEEXT_BUILTIN );
1441 mbCustom = ::get_flag( nExtFlags, EXC_STYLEEXT_CUSTOM );
1442 mbHidden = ::get_flag( nExtFlags, EXC_STYLEEXT_HIDDEN );
1443 if( mbBuiltin )
1445 rStrm.Ignore( 1 ); // category
1446 rStrm >> mnBuiltinId >> mnLevel;
1452 ScStyleSheet* XclImpStyle::CreateStyleSheet()
1454 // #i1624# #i1768# ignore unnamed user styles
1455 if( !mpStyleSheet && (maFinalName.Len() > 0) )
1457 bool bCreatePattern = false;
1458 XclImpXF* pXF = GetXFBuffer().GetXF( mnXfId );
1460 bool bDefStyle = mbBuiltin && (mnBuiltinId == EXC_STYLE_NORMAL);
1461 if( bDefStyle )
1463 // set all flags to true to get all items in XclImpXF::CreatePattern()
1464 if( pXF ) pXF->SetAllUsedFlags( true );
1465 // use existing "Default" style sheet
1466 mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find(
1467 ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) );
1468 OSL_ENSURE( mpStyleSheet, "XclImpStyle::CreateStyleSheet - Default style not found" );
1469 bCreatePattern = true;
1471 else
1473 /* #i103281# do not create another style sheet of the same name,
1474 if it exists already. This is needed to prevent that styles
1475 pasted from clipboard get duplicated over and over. */
1476 mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find( maFinalName, SFX_STYLE_FAMILY_PARA ) );
1477 if( !mpStyleSheet )
1479 mpStyleSheet = &static_cast< ScStyleSheet& >( GetStyleSheetPool().Make( maFinalName, SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_USERDEF ) );
1480 bCreatePattern = true;
1484 // bDefStyle==true omits default pool items in CreatePattern()
1485 if( bCreatePattern && mpStyleSheet && pXF )
1486 mpStyleSheet->GetItemSet().Put( pXF->CreatePattern( bDefStyle ).GetItemSet() );
1488 return mpStyleSheet;
1491 void XclImpStyle::CreateUserStyle( const String& rFinalName )
1493 maFinalName = rFinalName;
1494 if( !IsBuiltin() || mbCustom )
1495 CreateStyleSheet();
1498 // ----------------------------------------------------------------------------
1500 XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot& rRoot ) :
1501 XclImpRoot( rRoot )
1505 void XclImpXFBuffer::Initialize()
1507 maXFList.clear();
1508 maBuiltinStyles.clear();
1509 maUserStyles.clear();
1510 maStylesByXf.clear();
1513 void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
1515 XclImpXF* pXF = new XclImpXF( GetRoot() );
1516 pXF->ReadXF( rStrm );
1517 maXFList.push_back( pXF );
1520 void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
1522 XclImpStyle* pStyle = new XclImpStyle( GetRoot() );
1523 pStyle->ReadStyle( rStrm );
1524 (pStyle->IsBuiltin() ? maBuiltinStyles : maUserStyles).push_back( pStyle );
1525 OSL_ENSURE( maStylesByXf.count( pStyle->GetXfId() ) == 0, "XclImpXFBuffer::ReadStyle - multiple styles with equal XF identifier" );
1526 maStylesByXf[ pStyle->GetXfId() ] = pStyle;
1529 sal_uInt16 XclImpXFBuffer::GetFontIndex( sal_uInt16 nXFIndex ) const
1531 const XclImpXF* pXF = GetXF( nXFIndex );
1532 return pXF ? pXF->GetFontIndex() : EXC_FONT_NOTFOUND;
1535 const XclImpFont* XclImpXFBuffer::GetFont( sal_uInt16 nXFIndex ) const
1537 return GetFontBuffer().GetFont( GetFontIndex( nXFIndex ) );
1540 namespace {
1542 /** Functor for case-insensitive string comparison, usable in maps etc. */
1543 struct IgnoreCaseCompare
1545 inline bool operator()( const String& rName1, const String& rName2 ) const
1546 { return rName1.CompareIgnoreCaseToAscii( rName2 ) == COMPARE_LESS; }
1549 } // namespace
1551 void XclImpXFBuffer::CreateUserStyles()
1553 // calculate final names of all styles
1554 typedef ::std::map< String, XclImpStyle*, IgnoreCaseCompare > CellStyleNameMap;
1555 typedef ::std::vector< XclImpStyle* > XclImpStyleVector;
1557 CellStyleNameMap aCellStyles;
1558 XclImpStyleVector aConflictNameStyles;
1560 /* First, reserve style names that are built-in in Calc. This causes that
1561 imported cell styles get different unused names and thus do not try to
1562 overwrite these built-in styles. For BIFF4 workbooks (which contain a
1563 separate list of cell styles per sheet), reserve all existing styles if
1564 current sheet is not the first sheet (this styles buffer will be
1565 initialized again for every new sheet). This will create unique names
1566 for styles in different sheets with the same name. Assuming that the
1567 BIFF4W import filter is never used to import from clipboard... */
1568 bool bReserveAll = (GetBiff() == EXC_BIFF4) && (GetCurrScTab() > 0);
1569 SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
1570 String aStandardName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
1571 for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
1572 if( (pStyleSheet->GetName() != aStandardName) && (bReserveAll || !pStyleSheet->IsUserDefined()) )
1573 if( aCellStyles.count( pStyleSheet->GetName() ) == 0 )
1574 aCellStyles[ pStyleSheet->GetName() ] = 0;
1576 /* Calculate names of built-in styles. Store styles with reserved names
1577 in the aConflictNameStyles list. */
1578 for( XclImpStyleList::iterator itStyle = maBuiltinStyles.begin(); itStyle != maBuiltinStyles.end(); ++itStyle )
1580 String aStyleName = XclTools::GetBuiltInStyleName( itStyle->GetBuiltinId(), itStyle->GetName(), itStyle->GetLevel() );
1581 OSL_ENSURE( bReserveAll || (aCellStyles.count( aStyleName ) == 0),
1582 "XclImpXFBuffer::CreateUserStyles - multiple styles with equal built-in identifier" );
1583 if( aCellStyles.count( aStyleName ) > 0 )
1584 aConflictNameStyles.push_back( &(*itStyle) );
1585 else
1586 aCellStyles[ aStyleName ] = &(*itStyle);
1589 /* Calculate names of user defined styles. Store styles with reserved
1590 names in the aConflictNameStyles list. */
1591 for( XclImpStyleList::iterator itStyle = maUserStyles.begin(); itStyle != maUserStyles.end(); ++itStyle )
1593 // #i1624# #i1768# ignore unnamed user styles
1594 if( itStyle->GetName().Len() > 0 )
1596 if( aCellStyles.count( itStyle->GetName() ) > 0 )
1597 aConflictNameStyles.push_back( &(*itStyle) );
1598 else
1599 aCellStyles[ itStyle->GetName() ] = &(*itStyle);
1603 // find unused names for all styles with conflicting names
1604 for( XclImpStyleVector::iterator aIt = aConflictNameStyles.begin(), aEnd = aConflictNameStyles.end(); aIt != aEnd; ++aIt )
1606 XclImpStyle* pStyle = *aIt;
1607 String aUnusedName;
1608 sal_Int32 nIndex = 0;
1611 aUnusedName.Assign( pStyle->GetName() ).Append( ' ' ).Append( OUString::number( ++nIndex ) );
1613 while( aCellStyles.count( aUnusedName ) > 0 );
1614 aCellStyles[ aUnusedName ] = pStyle;
1617 // set final names and create user-defined and modified built-in cell styles
1618 for( CellStyleNameMap::iterator aIt = aCellStyles.begin(), aEnd = aCellStyles.end(); aIt != aEnd; ++aIt )
1619 if( aIt->second )
1620 aIt->second->CreateUserStyle( aIt->first );
1623 ScStyleSheet* XclImpXFBuffer::CreateStyleSheet( sal_uInt16 nXFIndex )
1625 XclImpStyleMap::iterator aIt = maStylesByXf.find( nXFIndex );
1626 return (aIt == maStylesByXf.end()) ? 0 : aIt->second->CreateStyleSheet();
1629 // Buffer for XF indexes in cells =============================================
1631 IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange )
1633 bool XclImpXFRange::Expand( SCROW nScRow, const XclImpXFIndex& rXFIndex )
1635 if( maXFIndex != rXFIndex )
1636 return false;
1638 if( mnScRow2 + 1 == nScRow )
1640 ++mnScRow2;
1641 return true;
1643 if( mnScRow1 > 0 && (mnScRow1 - 1 == nScRow) )
1645 --mnScRow1;
1646 return true;
1649 return false;
1652 bool XclImpXFRange::Expand( const XclImpXFRange& rNextRange )
1654 OSL_ENSURE( mnScRow2 < rNextRange.mnScRow1, "XclImpXFRange::Expand - rows out of order" );
1655 if( (maXFIndex == rNextRange.maXFIndex) && (mnScRow2 + 1 == rNextRange.mnScRow1) )
1657 mnScRow2 = rNextRange.mnScRow2;
1658 return true;
1660 return false;
1663 // ----------------------------------------------------------------------------
1665 void XclImpXFRangeColumn::SetDefaultXF( const XclImpXFIndex& rXFIndex )
1667 // List should be empty when inserting the default column format.
1668 // Later explicit SetXF() calls will break up this range.
1669 OSL_ENSURE( maIndexList.empty(), "XclImpXFRangeColumn::SetDefaultXF - Setting Default Column XF is not empty" );
1671 // insert a complete row range with one insert.
1672 maIndexList.push_back( new XclImpXFRange( 0, MAXROW, rXFIndex ) );
1675 // ----------------------------------------------------------------------------
1677 void XclImpXFRangeColumn::SetXF( SCROW nScRow, const XclImpXFIndex& rXFIndex )
1679 XclImpXFRange* pPrevRange;
1680 XclImpXFRange* pNextRange;
1681 sal_uLong nNextIndex;
1683 Find( pPrevRange, pNextRange, nNextIndex, nScRow );
1685 // previous range:
1686 // try to overwrite XF (if row is contained in) or try to expand range
1687 if( pPrevRange )
1689 if( pPrevRange->Contains( nScRow ) ) // overwrite old XF
1691 if( rXFIndex == pPrevRange->maXFIndex )
1692 return;
1694 SCROW nFirstScRow = pPrevRange->mnScRow1;
1695 SCROW nLastScRow = pPrevRange->mnScRow2;
1696 sal_uLong nIndex = nNextIndex - 1;
1697 XclImpXFRange* pThisRange = pPrevRange;
1698 pPrevRange = (nIndex > 0 && nIndex <= maIndexList.size()) ? &(maIndexList[ nIndex - 1 ]) : 0;
1700 if( nFirstScRow == nLastScRow ) // replace solely XF
1702 pThisRange->maXFIndex = rXFIndex;
1703 TryConcatPrev( nNextIndex ); // try to concat. next with this
1704 TryConcatPrev( nIndex ); // try to concat. this with previous
1706 else if( nFirstScRow == nScRow ) // replace first XF
1708 ++(pThisRange->mnScRow1);
1709 // try to concatenate with previous of this
1710 if( !pPrevRange || !pPrevRange->Expand( nScRow, rXFIndex ) )
1711 Insert( new XclImpXFRange( nScRow, rXFIndex ), nIndex );
1713 else if( nLastScRow == nScRow ) // replace last XF
1715 --(pThisRange->mnScRow2);
1716 if( !pNextRange || !pNextRange->Expand( nScRow, rXFIndex ) )
1717 Insert( new XclImpXFRange( nScRow, rXFIndex ), nNextIndex );
1719 else // insert in the middle of the range
1721 pThisRange->mnScRow1 = nScRow + 1;
1722 // List::Insert() moves entries towards end of list, so insert twice at nIndex
1723 Insert( new XclImpXFRange( nScRow, rXFIndex ), nIndex );
1724 Insert( new XclImpXFRange( nFirstScRow, nScRow - 1, pThisRange->maXFIndex ), nIndex );
1726 return;
1728 else if( pPrevRange->Expand( nScRow, rXFIndex ) ) // try to expand
1730 TryConcatPrev( nNextIndex ); // try to concatenate next with expanded
1731 return;
1735 // try to expand next range
1736 if( pNextRange && pNextRange->Expand( nScRow, rXFIndex ) )
1737 return;
1739 // create new range
1740 Insert( new XclImpXFRange( nScRow, rXFIndex ), nNextIndex );
1743 void XclImpXFRangeColumn::Insert(XclImpXFRange* pXFRange, sal_uLong nIndex)
1745 maIndexList.insert( maIndexList.begin() + nIndex, pXFRange );
1748 void XclImpXFRangeColumn::Find(
1749 XclImpXFRange*& rpPrevRange, XclImpXFRange*& rpNextRange,
1750 sal_uLong& rnNextIndex, SCROW nScRow )
1753 // test whether list is empty
1754 if( maIndexList.empty() )
1756 rpPrevRange = rpNextRange = 0;
1757 rnNextIndex = 0;
1758 return;
1761 rpPrevRange = &maIndexList.front();
1762 rpNextRange = &maIndexList.back();
1764 // test whether row is at end of list (contained in or behind last range)
1765 // rpPrevRange will contain a possible existing row
1766 if( rpNextRange->mnScRow1 <= nScRow )
1768 rpPrevRange = rpNextRange;
1769 rpNextRange = 0;
1770 rnNextIndex = maIndexList.size();
1771 return;
1774 // test whether row is at beginning of list (really before first range)
1775 if( nScRow < rpPrevRange->mnScRow1 )
1777 rpNextRange = rpPrevRange;
1778 rpPrevRange = 0;
1779 rnNextIndex = 0;
1780 return;
1783 // loop: find range entries before and after new row
1784 // break the loop if there is no more range between first and last -or-
1785 // if rpPrevRange contains nScRow (rpNextRange will never contain nScRow)
1786 sal_uLong nPrevIndex = 0;
1787 sal_uLong nMidIndex;
1788 rnNextIndex = maIndexList.size() - 1;
1789 XclImpXFRange* pMidRange;
1790 while( ((rnNextIndex - nPrevIndex) > 1) && (rpPrevRange->mnScRow2 < nScRow) )
1792 nMidIndex = (nPrevIndex + rnNextIndex) / 2;
1793 pMidRange = &maIndexList[nMidIndex];
1794 OSL_ENSURE( pMidRange, "XclImpXFRangeColumn::Find - missing XF index range" );
1795 if( nScRow < pMidRange->mnScRow1 ) // row is really before pMidRange
1797 rpNextRange = pMidRange;
1798 rnNextIndex = nMidIndex;
1800 else // row is in or after pMidRange
1802 rpPrevRange = pMidRange;
1803 nPrevIndex = nMidIndex;
1807 // find next rpNextRange if rpPrevRange contains nScRow
1808 if( nScRow <= rpPrevRange->mnScRow2 )
1810 rnNextIndex = nPrevIndex + 1;
1811 rpNextRange = &maIndexList[rnNextIndex];
1815 void XclImpXFRangeColumn::TryConcatPrev( sal_uLong nIndex )
1817 if( !nIndex || nIndex >= maIndexList.size() )
1818 return;
1820 XclImpXFRange& prevRange = maIndexList[ nIndex - 1 ];
1821 XclImpXFRange& nextRange = maIndexList[ nIndex ];
1823 if( prevRange.Expand( nextRange ) )
1824 maIndexList.erase( maIndexList.begin() + nIndex );
1827 // ----------------------------------------------------------------------------
1829 XclImpXFRangeBuffer::XclImpXFRangeBuffer( const XclImpRoot& rRoot ) :
1830 XclImpRoot( rRoot )
1834 XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1838 void XclImpXFRangeBuffer::Initialize()
1840 maColumns.clear();
1841 maHyperlinks.clear();
1842 maMergeList.RemoveAll();
1845 void XclImpXFRangeBuffer::SetXF( const ScAddress& rScPos, sal_uInt16 nXFIndex, XclImpXFInsertMode eMode )
1847 SCCOL nScCol = rScPos.Col();
1848 SCROW nScRow = rScPos.Row();
1850 // set cell XF's
1851 size_t nIndex = static_cast< size_t >( nScCol );
1852 if( maColumns.size() <= nIndex )
1853 maColumns.resize( nIndex + 1 );
1854 if( !maColumns[ nIndex ] )
1855 maColumns[ nIndex ].reset( new XclImpXFRangeColumn );
1856 // remember all Boolean cells, they will get 'Standard' number format
1857 maColumns[ nIndex ]->SetXF( nScRow, XclImpXFIndex( nXFIndex, eMode == xlXFModeBoolCell ) );
1859 // set "center across selection" and "fill" attribute for all following empty cells
1860 // ignore it on row default XFs
1861 if( eMode != xlXFModeRow )
1863 const XclImpXF* pXF = GetXFBuffer().GetXF( nXFIndex );
1864 if( pXF && ((pXF->GetHorAlign() == EXC_XF_HOR_CENTER_AS) || (pXF->GetHorAlign() == EXC_XF_HOR_FILL)) )
1866 // expand last merged range if this attribute is set repeatedly
1867 ScRange* pRange = maMergeList.empty() ? NULL : maMergeList.back();
1868 if (pRange && (pRange->aEnd.Row() == nScRow) && (pRange->aEnd.Col() + 1 == nScCol) && (eMode == xlXFModeBlank))
1869 pRange->aEnd.IncCol();
1870 else if( eMode != xlXFModeBlank ) // do not merge empty cells
1871 SetMerge( nScCol, nScRow );
1876 void XclImpXFRangeBuffer::SetXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1878 SetXF( rScPos, nXFIndex, xlXFModeCell );
1881 void XclImpXFRangeBuffer::SetBlankXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1883 SetXF( rScPos, nXFIndex, xlXFModeBlank );
1886 void XclImpXFRangeBuffer::SetBoolXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1888 SetXF( rScPos, nXFIndex, xlXFModeBoolCell );
1891 void XclImpXFRangeBuffer::SetRowDefXF( SCROW nScRow, sal_uInt16 nXFIndex )
1893 for( SCCOL nScCol = 0; nScCol <= MAXCOL; ++nScCol )
1894 SetXF( ScAddress( nScCol, nScRow, 0 ), nXFIndex, xlXFModeRow );
1897 void XclImpXFRangeBuffer::SetColumnDefXF( SCCOL nScCol, sal_uInt16 nXFIndex )
1899 // our array should not have values when creating the default column format.
1900 size_t nIndex = static_cast< size_t >( nScCol );
1901 if( maColumns.size() <= nIndex )
1902 maColumns.resize( nIndex + 1 );
1903 OSL_ENSURE( !maColumns[ nIndex ], "XclImpXFRangeBuffer::SetColumnDefXF - default column of XFs already has values" );
1904 maColumns[ nIndex ].reset( new XclImpXFRangeColumn );
1905 maColumns[ nIndex ]->SetDefaultXF( XclImpXFIndex( nXFIndex ) );
1908 void XclImpXFRangeBuffer::SetBorderLine( const ScRange& rRange, SCTAB nScTab, sal_uInt16 nLine )
1910 SCCOL nFromScCol = (nLine == BOX_LINE_RIGHT) ? rRange.aEnd.Col() : rRange.aStart.Col();
1911 SCROW nFromScRow = (nLine == BOX_LINE_BOTTOM) ? rRange.aEnd.Row() : rRange.aStart.Row();
1912 ScDocument& rDoc = GetDoc();
1914 const SvxBoxItem* pFromItem = static_cast< const SvxBoxItem* >(
1915 rDoc.GetAttr( nFromScCol, nFromScRow, nScTab, ATTR_BORDER ) );
1916 const SvxBoxItem* pToItem = static_cast< const SvxBoxItem* >(
1917 rDoc.GetAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, ATTR_BORDER ) );
1919 SvxBoxItem aNewItem( *pToItem );
1920 aNewItem.SetLine( pFromItem->GetLine( nLine ), nLine );
1921 rDoc.ApplyAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, aNewItem );
1924 void XclImpXFRangeBuffer::SetHyperlink( const XclRange& rXclRange, const String& rUrl )
1926 maHyperlinks.push_back( XclImpHyperlinkRange( rXclRange, rUrl ) );
1929 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol, SCROW nScRow )
1931 maMergeList.Append( ScRange( nScCol, nScRow, 0 ) );
1934 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol1, SCROW nScRow1, SCCOL nScCol2, SCROW nScRow2 )
1936 if( (nScCol1 < nScCol2) || (nScRow1 < nScRow2) )
1937 maMergeList.Append( ScRange( nScCol1, nScRow1, 0, nScCol2, nScRow2, 0 ) );
1940 void XclImpXFRangeBuffer::Finalize()
1942 ScDocument& rDoc = GetDoc();
1943 SCTAB nScTab = GetCurrScTab();
1945 // apply patterns
1946 XclImpXFBuffer& rXFBuffer = GetXFBuffer();
1947 for( XclImpXFRangeColumnVec::const_iterator aVBeg = maColumns.begin(), aVEnd = maColumns.end(), aVIt = aVBeg; aVIt != aVEnd; ++aVIt )
1949 // apply all cell styles of an existing column
1950 if( aVIt->get() )
1952 XclImpXFRangeColumn& rColumn = **aVIt;
1953 SCCOL nScCol = static_cast< SCCOL >( aVIt - aVBeg );
1954 list<ScAttrEntry> aAttrs;
1956 for (XclImpXFRangeColumn::IndexList::iterator itr = rColumn.begin(), itrEnd = rColumn.end();
1957 itr != itrEnd; ++itr)
1959 XclImpXFRange& rStyle = *itr;
1960 const XclImpXFIndex& rXFIndex = rStyle.maXFIndex;
1961 XclImpXF* pXF = rXFBuffer.GetXF( rXFIndex.GetXFIndex() );
1962 if (!pXF)
1963 continue;
1965 sal_uInt32 nForceScNumFmt = rXFIndex.IsBoolCell() ?
1966 GetNumFmtBuffer().GetStdScNumFmt() : NUMBERFORMAT_ENTRY_NOT_FOUND;
1968 pXF->ApplyPatternToAttrList(aAttrs, rStyle.mnScRow1, rStyle.mnScRow2, nForceScNumFmt);
1971 if (aAttrs.empty() || aAttrs.back().nRow != MAXROW)
1973 ScAttrEntry aEntry;
1974 aEntry.nRow = MAXROW;
1975 aEntry.pPattern = rDoc.GetDefPattern();
1976 aAttrs.push_back(aEntry);
1979 size_t nAttrSize = aAttrs.size();
1980 assert(nAttrSize > 0);
1981 ScAttrEntry* pData = new ScAttrEntry[nAttrSize];
1982 list<ScAttrEntry>::const_iterator itr = aAttrs.begin(), itrEnd = aAttrs.end();
1983 for (size_t i = 0; itr != itrEnd; ++itr, ++i)
1984 pData[i] = *itr;
1986 rDoc.SetAttrEntries(nScCol, nScTab, pData, static_cast<SCSIZE>(nAttrSize));
1990 // insert hyperlink cells
1991 for( XclImpHyperlinkList::const_iterator aLIt = maHyperlinks.begin(), aLEnd = maHyperlinks.end(); aLIt != aLEnd; ++aLIt )
1992 XclImpHyperlink::InsertUrl( GetRoot(), aLIt->first, aLIt->second );
1994 // apply cell merging
1995 for ( size_t i = 0, nRange = maMergeList.size(); i < nRange; ++i )
1997 const ScRange* pRange = maMergeList[ i ];
1998 const ScAddress& rStart = pRange->aStart;
1999 const ScAddress& rEnd = pRange->aEnd;
2000 bool bMultiCol = rStart.Col() != rEnd.Col();
2001 bool bMultiRow = rStart.Row() != rEnd.Row();
2002 // set correct right border
2003 if( bMultiCol )
2004 SetBorderLine( *pRange, nScTab, BOX_LINE_RIGHT );
2005 // set correct lower border
2006 if( bMultiRow )
2007 SetBorderLine( *pRange, nScTab, BOX_LINE_BOTTOM );
2008 // do merge
2009 if( bMultiCol || bMultiRow )
2010 rDoc.DoMerge( nScTab, rStart.Col(), rStart.Row(), rEnd.Col(), rEnd.Row() );
2011 // #i93609# merged range in a single row: test if manual row height is needed
2012 if( !bMultiRow )
2014 bool bTextWrap = static_cast< const SfxBoolItem* >( rDoc.GetAttr( rStart.Col(), rStart.Row(), rStart.Tab(), ATTR_LINEBREAK ) )->GetValue();
2015 if( !bTextWrap && (rDoc.GetCellType( rStart ) == CELLTYPE_EDIT) )
2016 if (const EditTextObject* pEditObj = rDoc.GetEditText(rStart))
2017 bTextWrap = pEditObj->GetParagraphCount() > 1;
2018 if( bTextWrap )
2019 GetOldRoot().pColRowBuff->SetManualRowHeight( rStart.Row() );
2024 // ============================================================================
2026 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */