1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
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"
59 #include "colrowst.hxx"
60 #include "svl/poolcach.hxx"
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
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);
102 ColorDataVec maColorData
;
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
);
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
)
153 OSL_ENSURE( rStrm
.GetRecLeft() == static_cast< sal_Size
>( 4 * nCount
),
154 "XclImpPalette::ReadPalette - size mismatch" );
156 maColorTable
.resize( nCount
);
158 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; ++nIndex
)
161 maColorTable
[ nIndex
] = aColor
.GetColor();
166 // FONT record - font information =============================================
168 XclImpFont::XclImpFont( const XclImpRoot
& rRoot
) :
170 mbHasCharSet( false ),
175 SetAllUsedFlags( false );
178 XclImpFont::XclImpFont( const XclImpRoot
& rRoot
, const XclFontData
& rFontData
) :
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
)
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();
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
)
228 ReadFontData2( rStrm
);
229 ReadFontName2( rStrm
);
233 ReadFontData2( rStrm
);
234 ReadFontColor( rStrm
);
235 ReadFontName2( rStrm
);
238 ReadFontData5( rStrm
);
239 ReadFontName2( rStrm
);
242 ReadFontData5( rStrm
);
243 ReadFontName8( rStrm
);
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
)
264 sal_uInt32 nHeight
, nStyle
, nColor
, nFontFlags1
, nFontFlags2
, nFontFlags3
;
265 sal_uInt16 nWeight
, nEscapem
;
269 rStrm
>> nHeight
>> nStyle
>> nWeight
>> nEscapem
>> nUnderl
;
273 rStrm
>> nFontFlags1
>> nFontFlags2
>> nFontFlags3
;
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 )
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;
320 SvxFontItem
aFontItem( eFtFamily
, maData
.maName
, EMPTY_STRING
, ePitch
, eTempTextEnc
, ATTR_FONT
);
322 // set only for valid script types
324 PUTITEM( aFontItem
, ATTR_FONT
, EE_CHAR_FONTINFO
);
326 PUTITEM( aFontItem
, ATTR_CJK_FONT
, EE_CHAR_FONTINFO_CJK
);
328 PUTITEM( aFontItem
, ATTR_CTL_FONT
, EE_CHAR_FONTINFO_CTL
);
331 // Font height (for all script types)
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
346 PUTITEM( SvxColorItem( maData
.maColor
, ATTR_FONT_COLOR
), ATTR_FONT_COLOR
, EE_CHAR_COLOR
);
348 // Font weight (for all script types)
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
);
360 SvxUnderlineItem
aUnderlItem( maData
.GetScUnderline(), ATTR_FONT_UNDERLINE
);
361 PUTITEM( aUnderlItem
, ATTR_FONT_UNDERLINE
, EE_CHAR_UNDERLINE
);
364 // Font posture (for all script types)
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
375 PUTITEM( SvxCrossedOutItem( maData
.GetScStrikeout(), ATTR_FONT_CROSSEDOUT
), ATTR_FONT_CROSSEDOUT
, EE_CHAR_STRIKEOUT
);
377 PUTITEM( SvxContourItem( maData
.mbOutline
, ATTR_FONT_CONTOUR
), ATTR_FONT_CONTOUR
, EE_CHAR_OUTLINE
);
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
) );
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
)
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
)
413 rStrm
>> maData
.mnHeight
>> nFlags
;
414 ReadFontColor( rStrm
);
415 rStrm
>> maData
.mnWeight
>> maData
.mnEscapem
>> maData
.mnUnderline
>> maData
.mnFamily
>> maData
.mnCharSet
;
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
);
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()
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
) )
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
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
480 mbHasWstrn
= (!mbHasAsian
&& !mbHasCmplx
) || aCharMap
.HasChar( 'A' );
485 // ----------------------------------------------------------------------------
487 XclImpFontBuffer::XclImpFontBuffer( const XclImpRoot
& rRoot
) :
494 // default font for form controls without own font information
495 XclFontData aCtrlFontData
;
502 aCtrlFontData
.maName
.AssignAscii( "Helv" );
503 aCtrlFontData
.mnHeight
= 160;
504 aCtrlFontData
.mnWeight
= EXC_FONTWGHT_BOLD
;
507 aCtrlFontData
.maName
.AssignAscii( "Tahoma" );
508 aCtrlFontData
.mnHeight
= 160;
509 aCtrlFontData
.mnWeight
= EXC_FONTWGHT_NORMAL
;
514 maCtrlFont
.SetFontData( aCtrlFontData
, false );
517 void XclImpFontBuffer::Initialize()
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. */
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
),
609 void XclImpNumFmtBuffer::Initialize()
613 InitializeImport(); // base class
616 void XclImpNumFmtBuffer::ReadFormat( XclImpStream
& rStrm
)
623 aFormat
= rStrm
.ReadByteString( false );
627 rStrm
.Ignore( 2 ); // in BIFF4 the index field exists, but is undefined
628 aFormat
= rStrm
.ReadByteString( false );
632 rStrm
>> mnNextXclIdx
;
633 aFormat
= rStrm
.ReadByteString( false );
637 rStrm
>> mnNextXclIdx
;
638 aFormat
= rStrm
.ReadUniString();
646 if( mnNextXclIdx
< 0xFFFF )
648 InsertFormat( mnNextXclIdx
, aFormat
);
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
664 short nType
= NUMBERFORMAT_DEFINED
;
666 if( rNumFmt
.maFormat
.Len() )
668 OUString
aFormat( rNumFmt
.maFormat
);
669 rFormatter
.PutandConvertEntry( aFormat
, nCheckPos
,
670 nType
, nKey
, LANGUAGE_ENGLISH_US
, rNumFmt
.meLanguage
);
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
);
776 sal_uInt16 nScIndent
= mnIndent
* 200; // 1 Excel unit == 10 pt == 200 twips
777 ScfTools::PutItem( rItemSet
, SfxUInt16Item( ATTR_INDENT
, nScIndent
), bSkipPoolDefs
);
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
);
883 bool XclImpCellBorder::HasAnyOuterBorder() const
886 (mbLeftUsed
&& (mnLeftLine
!= EXC_LINE_NONE
)) ||
887 (mbRightUsed
&& (mnRightLine
!= EXC_LINE_NONE
)) ||
888 (mbTopUsed
&& (mnTopLine
!= EXC_LINE_NONE
)) ||
889 (mbBottomUsed
&& (mnBottomLine
!= EXC_LINE_NONE
));
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 ] =
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
)
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 ]) );
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
);
948 SvxLineItem
aTLBRItem( ATTR_BORDER_TLBR
);
949 SvxLineItem
aBLTRItem( ATTR_BORDER_BLTR
);
950 ::editeng::SvxBorderLine aLine
;
951 if( lclConvertBorderLine( aLine
, rPalette
, mnDiagLine
, mnDiagColor
) )
954 aTLBRItem
.SetLine( &aLine
);
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
) )
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
) );
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
),
1062 XclImpXF::~XclImpXF()
1066 void XclImpXF::ReadXF2( XclImpStream
& rStrm
)
1068 sal_uInt8 nReadFont
, nReadNumFmt
, nFlags
;
1071 rStrm
>> nReadNumFmt
>> nFlags
;
1073 // XF type always cell, no parent, used flags always true
1074 SetAllUsedFlags( true );
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
)
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 ) );
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
)
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 ) );
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 ) );
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 ) );
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
)
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() )
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. */
1198 mbProtUsed
= !pParentXF
->mbProtUsed
|| !(maProtection
== pParentXF
->maProtection
);
1200 mbFontUsed
= !pParentXF
->mbFontUsed
|| (mnXclFont
!= pParentXF
->mnXclFont
);
1202 mbFmtUsed
= !pParentXF
->mbFmtUsed
|| (mnXclNumFmt
!= pParentXF
->mnXclNumFmt
);
1204 mbAlignUsed
= !pParentXF
->mbAlignUsed
|| !(maAlignment
== pParentXF
->maAlignment
);
1206 mbBorderUsed
= !pParentXF
->mbBorderUsed
|| !(maBorder
== pParentXF
->maBorder
);
1208 mbAreaUsed
= !pParentXF
->mbAreaUsed
|| !(maArea
== pParentXF
->maArea
);
1214 maProtection
.FillToItemSet( rItemSet
, bSkipPoolDefs
);
1218 GetFontBuffer().FillToItemSet( rItemSet
, EXC_FONTITEM_CELL
, mnXclFont
, bSkipPoolDefs
);
1223 GetNumFmtBuffer().FillToItemSet( rItemSet
, mnXclNumFmt
, bSkipPoolDefs
);
1224 // Trace occurrences of Windows date formats
1225 GetTracer().TraceDates( mnXclNumFmt
);
1230 maAlignment
.FillToItemSet( rItemSet
, GetFontBuffer().GetFont( mnXclFont
), bSkipPoolDefs
);
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
);
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
);
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
1275 ScPatternAttr
& rPat
= *mpPattern
;
1277 // insert into document
1278 ScDocument
& rDoc
= GetDoc();
1284 // Apply style sheet. Don't clear the direct formats.
1285 rPat
.SetStyleSheet(mpStyleSheet
, false);
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
1293 ScStyleSheetPool
* pStylePool
= rDoc
.GetStyleSheetPool();
1296 ScStyleSheet
* pStyleSheet
= static_cast<ScStyleSheet
*>(
1298 ScGlobal::GetRscString(STR_STYLENAME_STANDARD
), SFX_STYLE_FAMILY_PARA
));
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.
1323 if (!rAttrs
.empty() && rAttrs
.back().nRow
+ 1 < nRow1
)
1328 // Fill this gap with the default pattern.
1330 aEntry
.nRow
= nRow1
- 1;
1331 aEntry
.pPattern
= rDoc
.GetDefPattern();
1332 rAttrs
.push_back(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
),
1418 void XclImpStyle::ReadStyle( XclImpStream
& rStrm
)
1420 OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF3
);
1422 sal_uInt16 nXFIndex
;
1424 mnXfId
= nXFIndex
& EXC_STYLE_XFMASK
;
1425 mbBuiltin
= ::get_flag( nXFIndex
, EXC_STYLE_BUILTIN
);
1429 rStrm
>> mnBuiltinId
>> mnLevel
;
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
;
1440 mbBuiltin
= ::get_flag( nExtFlags
, EXC_STYLEEXT_BUILTIN
);
1441 mbCustom
= ::get_flag( nExtFlags
, EXC_STYLEEXT_CUSTOM
);
1442 mbHidden
= ::get_flag( nExtFlags
, EXC_STYLEEXT_HIDDEN
);
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
);
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;
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
) );
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
)
1498 // ----------------------------------------------------------------------------
1500 XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot
& rRoot
) :
1505 void XclImpXFBuffer::Initialize()
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
) );
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
; }
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
) );
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
) );
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
;
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
)
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
)
1638 if( mnScRow2
+ 1 == nScRow
)
1643 if( mnScRow1
> 0 && (mnScRow1
- 1 == nScRow
) )
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
;
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
);
1686 // try to overwrite XF (if row is contained in) or try to expand range
1689 if( pPrevRange
->Contains( nScRow
) ) // overwrite old XF
1691 if( rXFIndex
== pPrevRange
->maXFIndex
)
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
);
1728 else if( pPrevRange
->Expand( nScRow
, rXFIndex
) ) // try to expand
1730 TryConcatPrev( nNextIndex
); // try to concatenate next with expanded
1735 // try to expand next range
1736 if( pNextRange
&& pNextRange
->Expand( nScRow
, rXFIndex
) )
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;
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
;
1770 rnNextIndex
= maIndexList
.size();
1774 // test whether row is at beginning of list (really before first range)
1775 if( nScRow
< rpPrevRange
->mnScRow1
)
1777 rpNextRange
= rpPrevRange
;
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() )
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
) :
1834 XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1838 void XclImpXFRangeBuffer::Initialize()
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();
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();
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
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() );
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
)
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
)
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
2004 SetBorderLine( *pRange
, nScTab
, BOX_LINE_RIGHT
);
2005 // set correct lower border
2007 SetBorderLine( *pRange
, nScTab
, BOX_LINE_BOTTOM
);
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
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;
2019 GetOldRoot().pColRowBuff
->SetManualRowHeight( rStart
.Row() );
2024 // ============================================================================
2026 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */