1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xistyle.cxx,v $
10 * $Revision: 1.38.14.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
33 #include "xistyle.hxx"
34 #include <sfx2/printer.hxx>
35 #include <sfx2/objsh.hxx>
36 #include <svtools/ctrltool.hxx>
37 #include <svx/editobj.hxx>
38 #include "scitems.hxx"
39 #include <svx/fontitem.hxx>
40 #include <svx/fhgtitem.hxx>
41 #include <svx/wghtitem.hxx>
42 #include <svx/udlnitem.hxx>
43 #include <svx/postitem.hxx>
44 #include <svx/crsditem.hxx>
45 #include <svx/cntritem.hxx>
46 #include <svx/shdditem.hxx>
47 #include <svx/escpitem.hxx>
48 #include <svx/algitem.hxx>
49 #include <svx/boxitem.hxx>
50 #include <svx/bolnitem.hxx>
51 #include <svx/rotmodit.hxx>
52 #include <svx/colritem.hxx>
53 #include <svx/brshitem.hxx>
54 #include <svx/frmdiritem.hxx>
55 #include <svx/eeitem.hxx>
56 #include <svx/flstitem.hxx>
57 #include "document.hxx"
58 #include "docpool.hxx"
60 #include "stlpool.hxx"
61 #include "stlsheet.hxx"
63 #include "globstr.hrc"
64 #include "xltracer.hxx"
65 #include "xistream.hxx"
66 #include "xicontent.hxx"
69 #include "colrowst.hxx"
71 #include <cppuhelper/implbase1.hxx>
72 #include <com/sun/star/container/XIndexAccess.hpp>
73 #include <com/sun/star/beans/XPropertySet.hpp>
74 using namespace ::com::sun::star
;
76 typedef ::cppu::WeakImplHelper1
< container::XIndexAccess
> XIndexAccess_BASE
;
77 typedef ::std::vector
< ColorData
> ColorDataVec
;
79 class PaletteIndex
: public XIndexAccess_BASE
82 PaletteIndex( const ColorDataVec
& rColorDataTable
) : maColorData( rColorDataTable
) {}
84 // Methods XIndexAccess
85 virtual ::sal_Int32 SAL_CALL
getCount() throw (uno::RuntimeException
)
87 return maColorData
.size();
90 virtual uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (lang::IndexOutOfBoundsException
, lang::WrappedTargetException
, uno::RuntimeException
)
92 //--Index; // apparently the palette is already 1 based
93 return uno::makeAny( sal_Int32( maColorData
[ Index
] ) );
96 // Methods XElementAcess
97 virtual uno::Type SAL_CALL
getElementType() throw (uno::RuntimeException
)
99 return ::getCppuType( (sal_Int32
*)0 );
101 virtual ::sal_Bool SAL_CALL
hasElements() throw (uno::RuntimeException
)
103 return (maColorData
.size() > 0);
107 ColorDataVec maColorData
;
111 XclImpPalette::ExportPalette()
113 if( SfxObjectShell
* pDocShell
= mrRoot
.GetDocShell() )
115 // copy values in color palette
116 sal_Int16 nColors
= maColorTable
.size();
117 ColorDataVec aColors
;
118 aColors
.resize( nColors
);
119 for( sal_uInt16 nIndex
= 0; nIndex
< nColors
; ++nIndex
)
120 aColors
[ nIndex
] = GetColorData( nIndex
);
122 uno::Reference
< beans::XPropertySet
> xProps( pDocShell
->GetModel(), uno::UNO_QUERY
);
125 uno::Reference
< container::XIndexAccess
> xIndex( new PaletteIndex( aColors
) );
126 xProps
->setPropertyValue( CREATE_OUSTRING("ColorPalette"), uno::makeAny( xIndex
) );
131 // PALETTE record - color information =========================================
133 XclImpPalette::XclImpPalette( const XclImpRoot
& rRoot
) :
134 XclDefaultPalette( rRoot
), mrRoot( rRoot
)
138 void XclImpPalette::Initialize()
140 maColorTable
.clear();
143 ColorData
XclImpPalette::GetColorData( sal_uInt16 nXclIndex
) const
145 if( nXclIndex
>= EXC_COLOR_USEROFFSET
)
147 sal_uInt32 nIx
= nXclIndex
- EXC_COLOR_USEROFFSET
;
148 if( nIx
< maColorTable
.size() )
149 return maColorTable
[ nIx
];
151 return GetDefColorData( nXclIndex
);
154 void XclImpPalette::ReadPalette( XclImpStream
& rStrm
)
158 DBG_ASSERT( rStrm
.GetRecLeft() == static_cast< sal_Size
>( 4 * nCount
),
159 "XclImpPalette::ReadPalette - size mismatch" );
161 maColorTable
.resize( nCount
);
163 for( sal_uInt16 nIndex
= 0; nIndex
< nCount
; ++nIndex
)
166 maColorTable
[ nIndex
] = aColor
.GetColor();
171 // FONT record - font information =============================================
173 XclImpFont::XclImpFont( const XclImpRoot
& rRoot
) :
175 mbHasCharSet( false ),
180 SetAllUsedFlags( false );
183 XclImpFont::XclImpFont( const XclImpRoot
& rRoot
, const XclFontData
& rFontData
) :
186 SetFontData( rFontData
, false );
189 void XclImpFont::SetAllUsedFlags( bool bUsed
)
191 mbFontNameUsed
= mbHeightUsed
= mbColorUsed
= mbWeightUsed
= mbEscapemUsed
=
192 mbUnderlUsed
= mbItalicUsed
= mbStrikeUsed
= mbOutlineUsed
= mbShadowUsed
= bUsed
;
195 void XclImpFont::SetFontData( const XclFontData
& rFontData
, bool bHasCharSet
)
198 mbHasCharSet
= bHasCharSet
;
199 if( maData
.maStyle
.Len() )
201 if( SfxObjectShell
* pDocShell
= GetDocShell() )
203 if( const SvxFontListItem
* pInfoItem
= static_cast< const SvxFontListItem
* >(
204 pDocShell
->GetItem( SID_ATTR_CHAR_FONTLIST
) ) )
206 if( const FontList
* pFontList
= pInfoItem
->GetFontList() )
208 FontInfo
aFontInfo( pFontList
->Get( maData
.maName
, maData
.maStyle
) );
209 maData
.SetScWeight( aFontInfo
.GetWeight() );
210 maData
.SetScPosture( aFontInfo
.GetItalic() );
214 maData
.maStyle
.Erase();
217 SetAllUsedFlags( true );
220 rtl_TextEncoding
XclImpFont::GetFontEncoding() const
222 // #i63105# use text encoding from FONT record
223 // #i67768# BIFF2-BIFF4 FONT records do not contain character set
224 rtl_TextEncoding eFontEnc
= mbHasCharSet
? maData
.GetFontEncoding() : GetTextEncoding();
225 return (eFontEnc
== RTL_TEXTENCODING_DONTKNOW
) ? GetTextEncoding() : eFontEnc
;
228 void XclImpFont::ReadFont( XclImpStream
& rStrm
)
233 ReadFontData2( rStrm
);
234 ReadFontName2( rStrm
);
238 ReadFontData2( rStrm
);
239 ReadFontColor( rStrm
);
240 ReadFontName2( rStrm
);
243 ReadFontData5( rStrm
);
244 ReadFontName2( rStrm
);
247 ReadFontData5( rStrm
);
248 ReadFontName8( rStrm
);
255 SetAllUsedFlags( true );
258 void XclImpFont::ReadEfont( XclImpStream
& rStrm
)
260 ReadFontColor( rStrm
);
263 void XclImpFont::ReadCFFontBlock( XclImpStream
& rStrm
)
265 DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF8
);
266 if( GetBiff() != EXC_BIFF8
)
269 sal_uInt32 nHeight
, nStyle
, nColor
, nFontFlags1
, nFontFlags2
, nFontFlags3
;
270 sal_uInt16 nWeight
, nEscapem
;
274 rStrm
>> nHeight
>> nStyle
>> nWeight
>> nEscapem
>> nUnderl
;
278 rStrm
>> nFontFlags1
>> nFontFlags2
>> nFontFlags3
;
281 if( (mbHeightUsed
= (nHeight
<= 0x7FFF)) == true )
282 maData
.mnHeight
= static_cast< sal_uInt16
>( nHeight
);
283 if( (mbWeightUsed
= !::get_flag( nFontFlags1
, EXC_CF_FONT_STYLE
) && (nWeight
< 0x7FFF)) == true )
284 maData
.mnWeight
= static_cast< sal_uInt16
>( nWeight
);
285 if( (mbItalicUsed
= !::get_flag( nFontFlags1
, EXC_CF_FONT_STYLE
)) == true )
286 maData
.mbItalic
= ::get_flag( nStyle
, EXC_CF_FONT_STYLE
);
287 if( (mbUnderlUsed
= !::get_flag( nFontFlags3
, EXC_CF_FONT_UNDERL
) && (nUnderl
<= 0x7F)) == true )
288 maData
.mnUnderline
= nUnderl
;
289 if( (mbColorUsed
= (nColor
<= 0x7FFF)) == true )
290 maData
.maColor
= GetPalette().GetColor( static_cast< sal_uInt16
>( nColor
) );
291 if( (mbStrikeUsed
= !::get_flag( nFontFlags1
, EXC_CF_FONT_STRIKEOUT
)) == true )
292 maData
.mbStrikeout
= ::get_flag( nStyle
, EXC_CF_FONT_STRIKEOUT
);
295 void XclImpFont::FillToItemSet( SfxItemSet
& rItemSet
, XclFontItemType eType
, bool bSkipPoolDefs
) const
297 // true = edit engine Which-IDs (EE_CHAR_*); false = Calc Which-IDs (ATTR_*)
298 bool bEE
= eType
!= EXC_FONTITEM_CELL
;
300 // item = the item to put into the item set
301 // sc_which = the Calc Which-ID of the item
302 // ee_which = the edit engine Which-ID of the item
303 #define PUTITEM( item, sc_which, ee_which ) \
304 ScfTools::PutItem( rItemSet, item, (bEE ? (ee_which) : (sc_which)), bSkipPoolDefs )
307 // #i36997# do not set default Tahoma font from notes
308 bool bDefNoteFont
= (eType
== EXC_FONTITEM_NOTE
) && (maData
.maName
.EqualsIgnoreCaseAscii( "Tahoma" ));
309 if( mbFontNameUsed
&& !bDefNoteFont
)
311 rtl_TextEncoding eFontEnc
= maData
.GetFontEncoding();
312 rtl_TextEncoding eTempTextEnc
= (bEE
&& (eFontEnc
== GetTextEncoding())) ?
313 ScfTools::GetSystemTextEncoding() : eFontEnc
;
315 SvxFontItem
aFontItem( maData
.GetScFamily( GetTextEncoding() ), maData
.maName
, EMPTY_STRING
,
316 PITCH_DONTKNOW
, eTempTextEnc
, ATTR_FONT
);
317 // #91658# set only for valid script types
319 PUTITEM( aFontItem
, ATTR_FONT
, EE_CHAR_FONTINFO
);
321 PUTITEM( aFontItem
, ATTR_CJK_FONT
, EE_CHAR_FONTINFO_CJK
);
323 PUTITEM( aFontItem
, ATTR_CTL_FONT
, EE_CHAR_FONTINFO_CTL
);
326 // Font height (for all script types)
329 sal_Int32 nHeight
= maData
.mnHeight
;
330 if( bEE
&& (eType
!= EXC_FONTITEM_HF
) ) // do not convert header/footer height
331 nHeight
= (nHeight
* 127 + 36) / EXC_POINTS_PER_INCH
; // #98527# 1 in == 72 pt
333 SvxFontHeightItem
aHeightItem( nHeight
, 100, ATTR_FONT_HEIGHT
);
334 PUTITEM( aHeightItem
, ATTR_FONT_HEIGHT
, EE_CHAR_FONTHEIGHT
);
335 PUTITEM( aHeightItem
, ATTR_CJK_FONT_HEIGHT
, EE_CHAR_FONTHEIGHT_CJK
);
336 PUTITEM( aHeightItem
, ATTR_CTL_FONT_HEIGHT
, EE_CHAR_FONTHEIGHT_CTL
);
339 // Font color - pass AUTO_COL to item
341 PUTITEM( SvxColorItem( maData
.maColor
, ATTR_FONT_COLOR
), ATTR_FONT_COLOR
, EE_CHAR_COLOR
);
343 // Font weight (for all script types)
346 SvxWeightItem
aWeightItem( maData
.GetScWeight(), ATTR_FONT_WEIGHT
);
347 PUTITEM( aWeightItem
, ATTR_FONT_WEIGHT
, EE_CHAR_WEIGHT
);
348 PUTITEM( aWeightItem
, ATTR_CJK_FONT_WEIGHT
, EE_CHAR_WEIGHT_CJK
);
349 PUTITEM( aWeightItem
, ATTR_CTL_FONT_WEIGHT
, EE_CHAR_WEIGHT_CTL
);
355 SvxUnderlineItem
aUnderlItem( maData
.GetScUnderline(), ATTR_FONT_UNDERLINE
);
356 PUTITEM( aUnderlItem
, ATTR_FONT_UNDERLINE
, EE_CHAR_UNDERLINE
);
359 // Font posture (for all script types)
362 SvxPostureItem
aPostItem( maData
.GetScPosture(), ATTR_FONT_POSTURE
);
363 PUTITEM( aPostItem
, ATTR_FONT_POSTURE
, EE_CHAR_ITALIC
);
364 PUTITEM( aPostItem
, ATTR_CJK_FONT_POSTURE
, EE_CHAR_ITALIC_CJK
);
365 PUTITEM( aPostItem
, ATTR_CTL_FONT_POSTURE
, EE_CHAR_ITALIC_CTL
);
368 // Boolean attributes crossed out, contoured, shadowed
370 PUTITEM( SvxCrossedOutItem( maData
.GetScStrikeout(), ATTR_FONT_CROSSEDOUT
), ATTR_FONT_CROSSEDOUT
, EE_CHAR_STRIKEOUT
);
372 PUTITEM( SvxContourItem( maData
.mbOutline
, ATTR_FONT_CONTOUR
), ATTR_FONT_CONTOUR
, EE_CHAR_OUTLINE
);
374 PUTITEM( SvxShadowedItem( maData
.mbShadow
, ATTR_FONT_SHADOWED
), ATTR_FONT_SHADOWED
, EE_CHAR_SHADOW
);
376 // Super-/subscript: only on edit engine objects
377 if( mbEscapemUsed
&& bEE
)
378 rItemSet
.Put( SvxEscapementItem( maData
.GetScEscapement(), EE_CHAR_ESCAPEMENT
) );
383 void XclImpFont::WriteFontProperties( ScfPropertySet
& rPropSet
,
384 XclFontPropSetType eType
, const Color
* pFontColor
) const
386 GetFontPropSetHelper().WriteFontProperties(
387 rPropSet
, eType
, maData
, mbHasWstrn
, mbHasAsian
, mbHasCmplx
, pFontColor
);
390 void XclImpFont::ReadFontData2( XclImpStream
& rStrm
)
393 rStrm
>> maData
.mnHeight
>> nFlags
;
395 maData
.mnWeight
= ::get_flagvalue( nFlags
, EXC_FONTATTR_BOLD
, EXC_FONTWGHT_BOLD
, EXC_FONTWGHT_NORMAL
);
396 maData
.mnUnderline
= ::get_flagvalue( nFlags
, EXC_FONTATTR_UNDERLINE
, EXC_FONTUNDERL_SINGLE
, EXC_FONTUNDERL_NONE
);
397 maData
.mbItalic
= ::get_flag( nFlags
, EXC_FONTATTR_ITALIC
);
398 maData
.mbStrikeout
= ::get_flag( nFlags
, EXC_FONTATTR_STRIKEOUT
);
399 maData
.mbOutline
= ::get_flag( nFlags
, EXC_FONTATTR_OUTLINE
);
400 maData
.mbShadow
= ::get_flag( nFlags
, EXC_FONTATTR_SHADOW
);
401 mbHasCharSet
= false;
404 void XclImpFont::ReadFontData5( XclImpStream
& rStrm
)
408 rStrm
>> maData
.mnHeight
>> nFlags
;
409 ReadFontColor( rStrm
);
410 rStrm
>> maData
.mnWeight
>> maData
.mnEscapem
>> maData
.mnUnderline
>> maData
.mnFamily
>> maData
.mnCharSet
;
413 maData
.mbItalic
= ::get_flag( nFlags
, EXC_FONTATTR_ITALIC
);
414 maData
.mbStrikeout
= ::get_flag( nFlags
, EXC_FONTATTR_STRIKEOUT
);
415 maData
.mbOutline
= ::get_flag( nFlags
, EXC_FONTATTR_OUTLINE
);
416 maData
.mbShadow
= ::get_flag( nFlags
, EXC_FONTATTR_SHADOW
);
420 void XclImpFont::ReadFontColor( XclImpStream
& rStrm
)
422 maData
.maColor
= GetPalette().GetColor( rStrm
.ReaduInt16() );
425 void XclImpFont::ReadFontName2( XclImpStream
& rStrm
)
427 maData
.maName
= rStrm
.ReadByteString( false );
430 void XclImpFont::ReadFontName8( XclImpStream
& rStrm
)
432 maData
.maName
= rStrm
.ReadUniString( rStrm
.ReaduInt8() );
435 void XclImpFont::GuessScriptType()
438 mbHasAsian
= mbHasCmplx
= false;
440 // #91658# #113783# find the script types for which the font contains characters
441 if( OutputDevice
* pPrinter
= GetPrinter() )
443 Font
aFont( maData
.maName
, Size( 0, 10 ) );
444 FontCharMap aCharMap
;
446 pPrinter
->SetFont( aFont
);
447 if( pPrinter
->GetFontCharMap( aCharMap
) )
451 aCharMap
.HasChar( 0x3041 ) || // 3040-309F: Hiragana
452 aCharMap
.HasChar( 0x30A1 ) || // 30A0-30FF: Katakana
453 aCharMap
.HasChar( 0x3111 ) || // 3100-312F: Bopomofo
454 aCharMap
.HasChar( 0x3131 ) || // 3130-318F: Hangul Compatibility Jamo
455 aCharMap
.HasChar( 0x3301 ) || // 3300-33FF: CJK Compatibility
456 aCharMap
.HasChar( 0x3401 ) || // 3400-4DBF: CJK Unified Ideographs Extension A
457 aCharMap
.HasChar( 0x4E01 ) || // 4E00-9FAF: CJK Unified Ideographs
458 aCharMap
.HasChar( 0x7E01 ) || // 4E00-9FAF: CJK unified ideographs
459 aCharMap
.HasChar( 0xA001 ) || // A001-A48F: Yi Syllables
460 aCharMap
.HasChar( 0xAC01 ) || // AC00-D7AF: Hangul Syllables
461 aCharMap
.HasChar( 0xCC01 ) || // AC00-D7AF: Hangul Syllables
462 aCharMap
.HasChar( 0xF901 ) || // F900-FAFF: CJK Compatibility Ideographs
463 aCharMap
.HasChar( 0xFF71 ); // FF00-FFEF: Halfwidth/Fullwidth Forms
464 // #113783# CTL fonts
466 aCharMap
.HasChar( 0x05D1 ) || // 0590-05FF: Hebrew
467 aCharMap
.HasChar( 0x0631 ) || // 0600-06FF: Arabic
468 aCharMap
.HasChar( 0x0721 ) || // 0700-074F: Syriac
469 aCharMap
.HasChar( 0x0911 ) || // 0900-0DFF: Indic scripts
470 aCharMap
.HasChar( 0x0E01 ) || // 0E00-0E7F: Thai
471 aCharMap
.HasChar( 0xFB21 ) || // FB1D-FB4F: Hebrew Presentation Forms
472 aCharMap
.HasChar( 0xFB51 ) || // FB50-FDFF: Arabic Presentation Forms-A
473 aCharMap
.HasChar( 0xFE71 ); // FE70-FEFF: Arabic Presentation Forms-B
475 mbHasWstrn
= (!mbHasAsian
&& !mbHasCmplx
) || aCharMap
.HasChar( 'A' );
480 // ----------------------------------------------------------------------------
482 XclImpFontBuffer::XclImpFontBuffer( const XclImpRoot
& rRoot
) :
489 // default font for form controls without own font information
490 XclFontData aCtrlFontData
;
497 aCtrlFontData
.maName
.AssignAscii( "Helv" );
498 aCtrlFontData
.mnHeight
= 160;
499 aCtrlFontData
.mnWeight
= EXC_FONTWGHT_BOLD
;
502 aCtrlFontData
.maName
.AssignAscii( "Tahoma" );
503 aCtrlFontData
.mnHeight
= 160;
504 aCtrlFontData
.mnWeight
= EXC_FONTWGHT_NORMAL
;
509 maCtrlFont
.SetFontData( aCtrlFontData
, false );
512 void XclImpFontBuffer::Initialize()
516 // application font for column width calculation, later filled with first font from font list
517 XclFontData aAppFontData
;
518 aAppFontData
.maName
.AssignAscii( "Arial" );
519 aAppFontData
.mnHeight
= 200;
520 aAppFontData
.mnWeight
= EXC_FONTWGHT_NORMAL
;
521 UpdateAppFont( aAppFontData
, false );
524 const XclImpFont
* XclImpFontBuffer::GetFont( sal_uInt16 nFontIndex
) const
526 /* Font with index 4 is not stored in an Excel file, but used e.g. by
527 BIFF5 form pushbutton objects. It is the bold default font. */
528 return (nFontIndex
== 4) ? &maFont4
:
529 maFontList
.GetObject( (nFontIndex
< 4) ? nFontIndex
: (nFontIndex
- 1) );
532 void XclImpFontBuffer::ReadFont( XclImpStream
& rStrm
)
534 XclImpFont
* pFont
= new XclImpFont( GetRoot() );
535 pFont
->ReadFont( rStrm
);
536 maFontList
.Append( pFont
);
538 if( maFontList
.Count() == 1 )
540 UpdateAppFont( pFont
->GetFontData(), pFont
->HasCharSet() );
541 // #i71033# set text encoding from application font, if CODEPAGE is missing
542 SetAppFontEncoding( pFont
->GetFontEncoding() );
546 void XclImpFontBuffer::ReadEfont( XclImpStream
& rStrm
)
548 if( XclImpFont
* pFont
= maFontList
.Last() )
549 pFont
->ReadEfont( rStrm
);
552 void XclImpFontBuffer::FillToItemSet(
553 SfxItemSet
& rItemSet
, XclFontItemType eType
,
554 sal_uInt16 nFontIdx
, bool bSkipPoolDefs
) const
556 if( const XclImpFont
* pFont
= GetFont( nFontIdx
) )
557 pFont
->FillToItemSet( rItemSet
, eType
, bSkipPoolDefs
);
560 void XclImpFontBuffer::WriteFontProperties( ScfPropertySet
& rPropSet
,
561 XclFontPropSetType eType
, sal_uInt16 nFontIdx
, const Color
* pFontColor
) const
563 if( const XclImpFont
* pFont
= GetFont( nFontIdx
) )
564 pFont
->WriteFontProperties( rPropSet
, eType
, pFontColor
);
567 void XclImpFontBuffer::WriteDefaultCtrlFontProperties( ScfPropertySet
& rPropSet
) const
569 maCtrlFont
.WriteFontProperties( rPropSet
, EXC_FONTPROPSET_CONTROL
);
572 void XclImpFontBuffer::UpdateAppFont( const XclFontData
& rFontData
, bool bHasCharSet
)
574 maAppFont
= rFontData
;
575 // #i3006# Calculate the width of '0' from first font and current printer.
576 SetCharWidth( maAppFont
);
578 // font 4 is bold font 0
579 XclFontData
aFont4Data( maAppFont
);
580 aFont4Data
.mnWeight
= EXC_FONTWGHT_BOLD
;
581 maFont4
.SetFontData( aFont4Data
, bHasCharSet
);
584 // FORMAT record - number formats =============================================
586 XclImpNumFmtBuffer::XclImpNumFmtBuffer( const XclImpRoot
& rRoot
) :
587 XclNumFmtBuffer( rRoot
),
593 void XclImpNumFmtBuffer::Initialize()
597 InitializeImport(); // base class
600 void XclImpNumFmtBuffer::ReadFormat( XclImpStream
& rStrm
)
607 aFormat
= rStrm
.ReadByteString( false );
611 rStrm
.Ignore( 2 ); // in BIFF4 the index field exists, but is undefined
612 aFormat
= rStrm
.ReadByteString( false );
616 rStrm
>> mnNextXclIdx
;
617 aFormat
= rStrm
.ReadByteString( false );
621 rStrm
>> mnNextXclIdx
;
622 aFormat
= rStrm
.ReadUniString();
630 if( mnNextXclIdx
< 0xFFFF )
632 InsertFormat( mnNextXclIdx
, aFormat
);
637 void XclImpNumFmtBuffer::CreateScFormats()
639 DBG_ASSERT( maIndexMap
.empty(), "XclImpNumFmtBuffer::CreateScFormats - already created" );
641 SvNumberFormatter
& rFormatter
= GetFormatter();
642 for( XclNumFmtMap::const_iterator aIt
= GetFormatMap().begin(), aEnd
= GetFormatMap().end(); aIt
!= aEnd
; ++aIt
)
644 const XclNumFmt
& rNumFmt
= aIt
->second
;
646 // insert/convert the Excel number format
647 xub_StrLen nCheckPos
;
648 short nType
= NUMBERFORMAT_DEFINED
;
650 if( rNumFmt
.maFormat
.Len() )
652 String
aFormat( rNumFmt
.maFormat
);
653 rFormatter
.PutandConvertEntry( aFormat
, nCheckPos
,
654 nType
, nKey
, LANGUAGE_ENGLISH_US
, rNumFmt
.meLanguage
);
657 nKey
= rFormatter
.GetFormatIndex( rNumFmt
.meOffset
, rNumFmt
.meLanguage
);
659 // insert the resulting format key into the Excel->Calc index map
660 maIndexMap
[ aIt
->first
] = nKey
;
664 ULONG
XclImpNumFmtBuffer::GetScFormat( sal_uInt16 nXclNumFmt
) const
666 XclImpIndexMap::const_iterator aIt
= maIndexMap
.find( nXclNumFmt
);
667 return (aIt
!= maIndexMap
.end()) ? aIt
->second
: NUMBERFORMAT_ENTRY_NOT_FOUND
;
670 void XclImpNumFmtBuffer::FillToItemSet( SfxItemSet
& rItemSet
, sal_uInt16 nXclNumFmt
, bool bSkipPoolDefs
) const
672 ULONG nScNumFmt
= GetScFormat( nXclNumFmt
);
673 if( nScNumFmt
== NUMBERFORMAT_ENTRY_NOT_FOUND
)
674 nScNumFmt
= GetStdScNumFmt();
675 FillScFmtToItemSet( rItemSet
, nScNumFmt
, bSkipPoolDefs
);
678 void XclImpNumFmtBuffer::FillScFmtToItemSet( SfxItemSet
& rItemSet
, ULONG nScNumFmt
, bool bSkipPoolDefs
) const
680 DBG_ASSERT( nScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
, "XclImpNumFmtBuffer::FillScFmtToItemSet - invalid number format" );
681 ScfTools::PutItem( rItemSet
, SfxUInt32Item( ATTR_VALUE_FORMAT
, nScNumFmt
), bSkipPoolDefs
);
682 if( rItemSet
.GetItemState( ATTR_VALUE_FORMAT
, FALSE
) == SFX_ITEM_SET
)
683 ScGlobal::AddLanguage( rItemSet
, GetFormatter() );
686 // XF, STYLE record - Cell formatting =========================================
688 void XclImpCellProt::FillFromXF2( sal_uInt8 nNumFmt
)
690 mbLocked
= ::get_flag( nNumFmt
, EXC_XF2_LOCKED
);
691 mbHidden
= ::get_flag( nNumFmt
, EXC_XF2_HIDDEN
);
694 void XclImpCellProt::FillFromXF3( sal_uInt16 nProt
)
696 mbLocked
= ::get_flag( nProt
, EXC_XF_LOCKED
);
697 mbHidden
= ::get_flag( nProt
, EXC_XF_HIDDEN
);
700 void XclImpCellProt::FillToItemSet( SfxItemSet
& rItemSet
, bool bSkipPoolDefs
) const
702 ScfTools::PutItem( rItemSet
, ScProtectionAttr( mbLocked
, mbHidden
), bSkipPoolDefs
);
706 // ----------------------------------------------------------------------------
708 void XclImpCellAlign::FillFromXF2( sal_uInt8 nFlags
)
710 mnHorAlign
= ::extract_value
< sal_uInt8
>( nFlags
, 0, 3 );
713 void XclImpCellAlign::FillFromXF3( sal_uInt16 nAlign
)
715 mnHorAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 0, 3 );
716 mbLineBreak
= ::get_flag( nAlign
, EXC_XF_LINEBREAK
); // new in BIFF3
719 void XclImpCellAlign::FillFromXF4( sal_uInt16 nAlign
)
721 FillFromXF3( nAlign
);
722 mnVerAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 4, 2 ); // new in BIFF4
723 mnOrient
= ::extract_value
< sal_uInt8
>( nAlign
, 6, 2 ); // new in BIFF4
726 void XclImpCellAlign::FillFromXF5( sal_uInt16 nAlign
)
728 mnHorAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 0, 3 );
729 mnVerAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 4, 3 );
730 mbLineBreak
= ::get_flag( nAlign
, EXC_XF_LINEBREAK
);
731 mnOrient
= ::extract_value
< sal_uInt8
>( nAlign
, 8, 2 );
734 void XclImpCellAlign::FillFromXF8( sal_uInt16 nAlign
, sal_uInt16 nMiscAttrib
)
736 mnHorAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 0, 3 );
737 mnVerAlign
= ::extract_value
< sal_uInt8
>( nAlign
, 4, 3 );
738 mbLineBreak
= ::get_flag( nAlign
, EXC_XF_LINEBREAK
);
739 mnRotation
= ::extract_value
< sal_uInt8
>( nAlign
, 8, 8 ); // new in BIFF8
740 mnIndent
= ::extract_value
< sal_uInt8
>( nMiscAttrib
, 0, 4 ); // new in BIFF8
741 mbShrink
= ::get_flag( nMiscAttrib
, EXC_XF8_SHRINK
); // new in BIFF8
742 mnTextDir
= ::extract_value
< sal_uInt8
>( nMiscAttrib
, 6, 2 ); // new in BIFF8
745 void XclImpCellAlign::FillToItemSet( SfxItemSet
& rItemSet
, const XclImpFont
* pFont
, bool bSkipPoolDefs
) const
747 // horizontal alignment
748 ScfTools::PutItem( rItemSet
, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY
), bSkipPoolDefs
);
750 // text wrap (#i74508# always if vertical alignment is justified or distributed)
751 bool bLineBreak
= mbLineBreak
|| (mnVerAlign
== EXC_XF_VER_JUSTIFY
) || (mnVerAlign
== EXC_XF_VER_DISTRIB
);
752 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_LINEBREAK
, bLineBreak
), bSkipPoolDefs
);
754 // vertical alignment
755 ScfTools::PutItem( rItemSet
, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY
), bSkipPoolDefs
);
758 sal_uInt16 nScIndent
= mnIndent
* 200; // 1 Excel unit == 10 pt == 200 twips
759 ScfTools::PutItem( rItemSet
, SfxUInt16Item( ATTR_INDENT
, nScIndent
), bSkipPoolDefs
);
762 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_SHRINKTOFIT
, mbShrink
), bSkipPoolDefs
);
764 // text orientation/rotation (BIFF2-BIFF7 sets mnOrient)
765 sal_uInt8 nXclRot
= (mnOrient
== EXC_ORIENT_NONE
) ? mnRotation
: XclTools::GetXclRotFromOrient( mnOrient
);
766 bool bStacked
= (nXclRot
== EXC_ROT_STACKED
);
767 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_STACKED
, bStacked
), bSkipPoolDefs
);
768 ScfTools::PutItem( rItemSet
, SvxRotateModeItem( SVX_ROTATE_MODE_STANDARD
, ATTR_ROTATE_MODE
), bSkipPoolDefs
);
769 // set an angle in the range from -90 to 90 degrees
770 sal_Int32 nAngle
= XclTools::GetScRotation( nXclRot
, 0 );
771 ScfTools::PutItem( rItemSet
, SfxInt32Item( ATTR_ROTATE_VALUE
, nAngle
), bSkipPoolDefs
);
772 // #105933# set "Use asian vertical layout", if cell is stacked and font contains CKJ characters
773 bool bAsianVert
= bStacked
&& pFont
&& pFont
->HasAsianChars();
774 ScfTools::PutItem( rItemSet
, SfxBoolItem( ATTR_VERTICAL_ASIAN
, bAsianVert
), bSkipPoolDefs
);
776 // CTL text direction
777 ScfTools::PutItem( rItemSet
, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR
), bSkipPoolDefs
);
780 // ----------------------------------------------------------------------------
782 XclImpCellBorder::XclImpCellBorder()
784 SetUsedFlags( false, false );
787 void XclImpCellBorder::SetUsedFlags( bool bOuterUsed
, bool bDiagUsed
)
789 mbLeftUsed
= mbRightUsed
= mbTopUsed
= mbBottomUsed
= bOuterUsed
;
790 mbDiagUsed
= bDiagUsed
;
793 void XclImpCellBorder::FillFromXF2( sal_uInt8 nFlags
)
795 mnLeftLine
= ::get_flagvalue( nFlags
, EXC_XF2_LEFTLINE
, EXC_LINE_THIN
, EXC_LINE_NONE
);
796 mnRightLine
= ::get_flagvalue( nFlags
, EXC_XF2_RIGHTLINE
, EXC_LINE_THIN
, EXC_LINE_NONE
);
797 mnTopLine
= ::get_flagvalue( nFlags
, EXC_XF2_TOPLINE
, EXC_LINE_THIN
, EXC_LINE_NONE
);
798 mnBottomLine
= ::get_flagvalue( nFlags
, EXC_XF2_BOTTOMLINE
, EXC_LINE_THIN
, EXC_LINE_NONE
);
799 mnLeftColor
= mnRightColor
= mnTopColor
= mnBottomColor
= EXC_COLOR_BIFF2_BLACK
;
800 SetUsedFlags( true, false );
803 void XclImpCellBorder::FillFromXF3( sal_uInt32 nBorder
)
805 mnTopLine
= ::extract_value
< sal_uInt8
>( nBorder
, 0, 3 );
806 mnLeftLine
= ::extract_value
< sal_uInt8
>( nBorder
, 8, 3 );
807 mnBottomLine
= ::extract_value
< sal_uInt8
>( nBorder
, 16, 3 );
808 mnRightLine
= ::extract_value
< sal_uInt8
>( nBorder
, 24, 3 );
809 mnTopColor
= ::extract_value
< sal_uInt16
>( nBorder
, 3, 5 );
810 mnLeftColor
= ::extract_value
< sal_uInt16
>( nBorder
, 11, 5 );
811 mnBottomColor
= ::extract_value
< sal_uInt16
>( nBorder
, 19, 5 );
812 mnRightColor
= ::extract_value
< sal_uInt16
>( nBorder
, 27, 5 );
813 SetUsedFlags( true, false );
816 void XclImpCellBorder::FillFromXF5( sal_uInt32 nBorder
, sal_uInt32 nArea
)
818 mnTopLine
= ::extract_value
< sal_uInt8
>( nBorder
, 0, 3 );
819 mnLeftLine
= ::extract_value
< sal_uInt8
>( nBorder
, 3, 3 );
820 mnBottomLine
= ::extract_value
< sal_uInt8
>( nArea
, 22, 3 );
821 mnRightLine
= ::extract_value
< sal_uInt8
>( nBorder
, 6, 3 );
822 mnTopColor
= ::extract_value
< sal_uInt16
>( nBorder
, 9, 7 );
823 mnLeftColor
= ::extract_value
< sal_uInt16
>( nBorder
, 16, 7 );
824 mnBottomColor
= ::extract_value
< sal_uInt16
>( nArea
, 25, 7 );
825 mnRightColor
= ::extract_value
< sal_uInt16
>( nBorder
, 23, 7 );
826 SetUsedFlags( true, false );
829 void XclImpCellBorder::FillFromXF8( sal_uInt32 nBorder1
, sal_uInt32 nBorder2
)
831 mnLeftLine
= ::extract_value
< sal_uInt8
>( nBorder1
, 0, 4 );
832 mnRightLine
= ::extract_value
< sal_uInt8
>( nBorder1
, 4, 4 );
833 mnTopLine
= ::extract_value
< sal_uInt8
>( nBorder1
, 8, 4 );
834 mnBottomLine
= ::extract_value
< sal_uInt8
>( nBorder1
, 12, 4 );
835 mnLeftColor
= ::extract_value
< sal_uInt16
>( nBorder1
, 16, 7 );
836 mnRightColor
= ::extract_value
< sal_uInt16
>( nBorder1
, 23, 7 );
837 mnTopColor
= ::extract_value
< sal_uInt16
>( nBorder2
, 0, 7 );
838 mnBottomColor
= ::extract_value
< sal_uInt16
>( nBorder2
, 7, 7 );
839 mbDiagTLtoBR
= ::get_flag( nBorder1
, EXC_XF_DIAGONAL_TL_TO_BR
);
840 mbDiagBLtoTR
= ::get_flag( nBorder1
, EXC_XF_DIAGONAL_BL_TO_TR
);
841 if( mbDiagTLtoBR
|| mbDiagBLtoTR
)
843 mnDiagLine
= ::extract_value
< sal_uInt8
>( nBorder2
, 21, 4 );
844 mnDiagColor
= ::extract_value
< sal_uInt16
>( nBorder2
, 14, 7 );
846 SetUsedFlags( true, true );
849 void XclImpCellBorder::FillFromCF8( sal_uInt16 nLineStyle
, sal_uInt32 nLineColor
, sal_uInt32 nFlags
)
851 mnLeftLine
= ::extract_value
< sal_uInt8
>( nLineStyle
, 0, 4 );
852 mnRightLine
= ::extract_value
< sal_uInt8
>( nLineStyle
, 4, 4 );
853 mnTopLine
= ::extract_value
< sal_uInt8
>( nLineStyle
, 8, 4 );
854 mnBottomLine
= ::extract_value
< sal_uInt8
>( nLineStyle
, 12, 4 );
855 mnLeftColor
= ::extract_value
< sal_uInt16
>( nLineColor
, 0, 7 );
856 mnRightColor
= ::extract_value
< sal_uInt16
>( nLineColor
, 7, 7 );
857 mnTopColor
= ::extract_value
< sal_uInt16
>( nLineColor
, 16, 7 );
858 mnBottomColor
= ::extract_value
< sal_uInt16
>( nLineColor
, 23, 7 );
859 mbLeftUsed
= !::get_flag( nFlags
, EXC_CF_BORDER_LEFT
);
860 mbRightUsed
= !::get_flag( nFlags
, EXC_CF_BORDER_RIGHT
);
861 mbTopUsed
= !::get_flag( nFlags
, EXC_CF_BORDER_TOP
);
862 mbBottomUsed
= !::get_flag( nFlags
, EXC_CF_BORDER_BOTTOM
);
868 /** Converts the passed line style to a SvxBorderLine, or returns false, if style is "no line". */
869 bool lclConvertBorderLine( SvxBorderLine
& rLine
, const XclImpPalette
& rPalette
, sal_uInt8 nXclLine
, sal_uInt16 nXclColor
)
871 static const sal_uInt16 ppnLineParam
[][ 3 ] =
873 // outer width, inner width, distance
874 { 0, 0, 0 }, // 0 = none
875 { DEF_LINE_WIDTH_1
, 0, 0 }, // 1 = thin
876 { DEF_LINE_WIDTH_2
, 0, 0 }, // 2 = medium
877 { DEF_LINE_WIDTH_1
, 0, 0 }, // 3 = dashed
878 { DEF_LINE_WIDTH_0
, 0, 0 }, // 4 = dotted
879 { DEF_LINE_WIDTH_3
, 0, 0 }, // 5 = thick
880 { DEF_LINE_WIDTH_1
, DEF_LINE_WIDTH_1
, DEF_LINE_WIDTH_1
}, // 6 = double
881 { DEF_LINE_WIDTH_0
, 0, 0 }, // 7 = hair
882 { DEF_LINE_WIDTH_2
, 0, 0 }, // 8 = med dash
883 { DEF_LINE_WIDTH_1
, 0, 0 }, // 9 = thin dashdot
884 { DEF_LINE_WIDTH_2
, 0, 0 }, // A = med dashdot
885 { DEF_LINE_WIDTH_1
, 0, 0 }, // B = thin dashdotdot
886 { DEF_LINE_WIDTH_2
, 0, 0 }, // C = med dashdotdot
887 { DEF_LINE_WIDTH_2
, 0, 0 } // D = med slant dashdot
890 if( nXclLine
== EXC_LINE_NONE
)
892 if( nXclLine
>= STATIC_TABLE_SIZE( ppnLineParam
) )
893 nXclLine
= EXC_LINE_THIN
;
895 rLine
.SetColor( rPalette
.GetColor( nXclColor
) );
896 rLine
.SetOutWidth( ppnLineParam
[ nXclLine
][ 0 ] );
897 rLine
.SetInWidth( ppnLineParam
[ nXclLine
][ 1 ] );
898 rLine
.SetDistance( ppnLineParam
[ nXclLine
][ 2 ] );
904 void XclImpCellBorder::FillToItemSet( SfxItemSet
& rItemSet
, const XclImpPalette
& rPalette
, bool bSkipPoolDefs
) const
906 if( mbLeftUsed
|| mbRightUsed
|| mbTopUsed
|| mbBottomUsed
)
908 SvxBoxItem
aBoxItem( ATTR_BORDER
);
910 if( mbLeftUsed
&& lclConvertBorderLine( aLine
, rPalette
, mnLeftLine
, mnLeftColor
) )
911 aBoxItem
.SetLine( &aLine
, BOX_LINE_LEFT
);
912 if( mbRightUsed
&& lclConvertBorderLine( aLine
, rPalette
, mnRightLine
, mnRightColor
) )
913 aBoxItem
.SetLine( &aLine
, BOX_LINE_RIGHT
);
914 if( mbTopUsed
&& lclConvertBorderLine( aLine
, rPalette
, mnTopLine
, mnTopColor
) )
915 aBoxItem
.SetLine( &aLine
, BOX_LINE_TOP
);
916 if( mbBottomUsed
&& lclConvertBorderLine( aLine
, rPalette
, mnBottomLine
, mnBottomColor
) )
917 aBoxItem
.SetLine( &aLine
, BOX_LINE_BOTTOM
);
918 ScfTools::PutItem( rItemSet
, aBoxItem
, bSkipPoolDefs
);
922 SvxLineItem
aTLBRItem( ATTR_BORDER_TLBR
);
923 SvxLineItem
aBLTRItem( ATTR_BORDER_BLTR
);
925 if( lclConvertBorderLine( aLine
, rPalette
, mnDiagLine
, mnDiagColor
) )
928 aTLBRItem
.SetLine( &aLine
);
930 aBLTRItem
.SetLine( &aLine
);
932 ScfTools::PutItem( rItemSet
, aTLBRItem
, bSkipPoolDefs
);
933 ScfTools::PutItem( rItemSet
, aBLTRItem
, bSkipPoolDefs
);
937 // ----------------------------------------------------------------------------
939 XclImpCellArea::XclImpCellArea()
941 SetUsedFlags( false );
944 void XclImpCellArea::SetUsedFlags( bool bUsed
)
946 mbForeUsed
= mbBackUsed
= mbPattUsed
= bUsed
;
949 void XclImpCellArea::FillFromXF2( sal_uInt8 nFlags
)
951 mnPattern
= ::get_flagvalue( nFlags
, EXC_XF2_BACKGROUND
, EXC_PATT_12_5_PERC
, EXC_PATT_NONE
);
952 mnForeColor
= EXC_COLOR_BIFF2_BLACK
;
953 mnBackColor
= EXC_COLOR_BIFF2_WHITE
;
954 SetUsedFlags( true );
957 void XclImpCellArea::FillFromXF3( sal_uInt16 nArea
)
959 mnPattern
= ::extract_value
< sal_uInt8
>( nArea
, 0, 6 );
960 mnForeColor
= ::extract_value
< sal_uInt16
>( nArea
, 6, 5 );
961 mnBackColor
= ::extract_value
< sal_uInt16
>( nArea
, 11, 5 );
962 SetUsedFlags( true );
965 void XclImpCellArea::FillFromXF5( sal_uInt32 nArea
)
967 mnPattern
= ::extract_value
< sal_uInt8
>( nArea
, 16, 6 );
968 mnForeColor
= ::extract_value
< sal_uInt16
>( nArea
, 0, 7 );
969 mnBackColor
= ::extract_value
< sal_uInt16
>( nArea
, 7, 7 );
970 SetUsedFlags( true );
973 void XclImpCellArea::FillFromXF8( sal_uInt32 nBorder2
, sal_uInt16 nArea
)
975 mnPattern
= ::extract_value
< sal_uInt8
>( nBorder2
, 26, 6 );
976 mnForeColor
= ::extract_value
< sal_uInt16
>( nArea
, 0, 7 );
977 mnBackColor
= ::extract_value
< sal_uInt16
>( nArea
, 7, 7 );
978 SetUsedFlags( true );
981 void XclImpCellArea::FillFromCF8( sal_uInt16 nPattern
, sal_uInt16 nColor
, sal_uInt32 nFlags
)
983 mnForeColor
= ::extract_value
< sal_uInt16
>( nColor
, 0, 7 );
984 mnBackColor
= ::extract_value
< sal_uInt16
>( nColor
, 7, 7 );
985 mnPattern
= ::extract_value
< sal_uInt8
>( nPattern
, 10, 6 );
986 mbForeUsed
= !::get_flag( nFlags
, EXC_CF_AREA_FGCOLOR
);
987 mbBackUsed
= !::get_flag( nFlags
, EXC_CF_AREA_BGCOLOR
);
988 mbPattUsed
= !::get_flag( nFlags
, EXC_CF_AREA_PATTERN
);
990 if( mbBackUsed
&& (!mbPattUsed
|| (mnPattern
== EXC_PATT_SOLID
)) )
992 mnForeColor
= mnBackColor
;
993 mnPattern
= EXC_PATT_SOLID
;
994 mbForeUsed
= mbPattUsed
= true;
996 else if( !mbBackUsed
&& mbPattUsed
&& (mnPattern
== EXC_PATT_SOLID
) )
1002 void XclImpCellArea::FillToItemSet( SfxItemSet
& rItemSet
, const XclImpPalette
& rPalette
, bool bSkipPoolDefs
) const
1004 if( mbPattUsed
) // colors may be both unused in cond. formats
1006 SvxBrushItem
aBrushItem( ATTR_BACKGROUND
);
1008 // #108935# do not use IsTransparent() - old Calc filter writes tranparency with different color indexes
1009 if( mnPattern
== EXC_PATT_NONE
)
1011 aBrushItem
.SetColor( Color( COL_TRANSPARENT
) );
1015 Color
aFore( rPalette
.GetColor( mbForeUsed
? mnForeColor
: EXC_COLOR_WINDOWTEXT
) );
1016 Color
aBack( rPalette
.GetColor( mbBackUsed
? mnBackColor
: EXC_COLOR_WINDOWBACK
) );
1017 aBrushItem
.SetColor( XclTools::GetPatternColor( aFore
, aBack
, mnPattern
) );
1020 ScfTools::PutItem( rItemSet
, aBrushItem
, bSkipPoolDefs
);
1025 // ----------------------------------------------------------------------------
1027 XclImpXF::XclImpXF( const XclImpRoot
& rRoot
) :
1028 XclXFBase( true ), // default is cell XF
1029 XclImpRoot( rRoot
),
1033 mbWasBuiltIn( false ),
1034 mbForceCreate( false )
1038 XclImpXF::~XclImpXF()
1042 void XclImpXF::ReadXF2( XclImpStream
& rStrm
)
1044 sal_uInt8 nReadFont
, nReadNumFmt
, nFlags
;
1047 rStrm
>> nReadNumFmt
>> nFlags
;
1049 // XF type always cell, no parent, used flags always true
1050 SetAllUsedFlags( true );
1053 maProtection
.FillFromXF2( nReadNumFmt
);
1054 mnXclFont
= nReadFont
;
1055 mnXclNumFmt
= nReadNumFmt
& EXC_XF2_VALFMT_MASK
;
1056 maAlignment
.FillFromXF2( nFlags
);
1057 maBorder
.FillFromXF2( nFlags
);
1058 maArea
.FillFromXF2( nFlags
);
1061 void XclImpXF::ReadXF3( XclImpStream
& rStrm
)
1064 sal_uInt16 nTypeProt
, nAlign
, nArea
;
1065 sal_uInt8 nReadFont
, nReadNumFmt
;
1066 rStrm
>> nReadFont
>> nReadNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1068 // XF type/parent, attribute used flags
1069 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
); // new in BIFF3
1070 mnParent
= ::extract_value
< sal_uInt16
>( nAlign
, 4, 12 ); // new in BIFF3
1071 SetUsedFlags( ::extract_value
< sal_uInt8
>( nTypeProt
, 10, 6 ) );
1074 maProtection
.FillFromXF3( nTypeProt
);
1075 mnXclFont
= nReadFont
;
1076 mnXclNumFmt
= nReadNumFmt
;
1077 maAlignment
.FillFromXF3( nAlign
);
1078 maBorder
.FillFromXF3( nBorder
);
1079 maArea
.FillFromXF3( nArea
); // new in BIFF3
1082 void XclImpXF::ReadXF4( XclImpStream
& rStrm
)
1085 sal_uInt16 nTypeProt
, nAlign
, nArea
;
1086 sal_uInt8 nReadFont
, nReadNumFmt
;
1087 rStrm
>> nReadFont
>> nReadNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1089 // XF type/parent, attribute used flags
1090 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1091 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1092 SetUsedFlags( ::extract_value
< sal_uInt8
>( nAlign
, 10, 6 ) );
1095 maProtection
.FillFromXF3( nTypeProt
);
1096 mnXclFont
= nReadFont
;
1097 mnXclNumFmt
= nReadNumFmt
;
1098 maAlignment
.FillFromXF4( nAlign
);
1099 maBorder
.FillFromXF3( nBorder
);
1100 maArea
.FillFromXF3( nArea
);
1103 void XclImpXF::ReadXF5( XclImpStream
& rStrm
)
1105 sal_uInt32 nArea
, nBorder
;
1106 sal_uInt16 nTypeProt
, nAlign
;
1107 rStrm
>> mnXclFont
>> mnXclNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1109 // XF type/parent, attribute used flags
1110 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1111 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1112 SetUsedFlags( ::extract_value
< sal_uInt8
>( nAlign
, 10, 6 ) );
1115 maProtection
.FillFromXF3( nTypeProt
);
1116 maAlignment
.FillFromXF5( nAlign
);
1117 maBorder
.FillFromXF5( nBorder
, nArea
);
1118 maArea
.FillFromXF5( nArea
);
1121 void XclImpXF::ReadXF8( XclImpStream
& rStrm
)
1123 sal_uInt32 nBorder1
, nBorder2
;
1124 sal_uInt16 nTypeProt
, nAlign
, nMiscAttrib
, nArea
;
1125 rStrm
>> mnXclFont
>> mnXclNumFmt
>> nTypeProt
>> nAlign
>> nMiscAttrib
>> nBorder1
>> nBorder2
>> nArea
;
1127 // XF type/parent, attribute used flags
1128 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1129 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1130 SetUsedFlags( ::extract_value
< sal_uInt8
>( nMiscAttrib
, 10, 6 ) );
1133 maProtection
.FillFromXF3( nTypeProt
);
1134 maAlignment
.FillFromXF8( nAlign
, nMiscAttrib
);
1135 maBorder
.FillFromXF8( nBorder1
, nBorder2
);
1136 maArea
.FillFromXF8( nBorder2
, nArea
);
1139 void XclImpXF::ReadXF( XclImpStream
& rStrm
)
1143 case EXC_BIFF2
: ReadXF2( rStrm
); break;
1144 case EXC_BIFF3
: ReadXF3( rStrm
); break;
1145 case EXC_BIFF4
: ReadXF4( rStrm
); break;
1146 case EXC_BIFF5
: ReadXF5( rStrm
); break;
1147 case EXC_BIFF8
: ReadXF8( rStrm
); break;
1148 default: DBG_ERROR_BIFF();
1152 void XclImpXF::SetStyleName( const String
& rStyleName
)
1154 DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
1155 DBG_ASSERT( rStyleName
.Len(), "XclImpXF::SetStyleName - style name empty" );
1156 if( IsStyleXF() && !maStyleName
.Len() )
1158 maStyleName
= rStyleName
;
1159 mbForceCreate
= true;
1163 void XclImpXF::SetBuiltInStyleName( sal_uInt8 nStyleId
, sal_uInt8 nLevel
)
1165 DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
1166 if( IsStyleXF() && !maStyleName
.Len() )
1168 mbWasBuiltIn
= true;
1169 maStyleName
= XclTools::GetBuiltInStyleName( nStyleId
, nLevel
);
1170 mbForceCreate
= nStyleId
== EXC_STYLE_NORMAL
; // force creation of "Default" style
1174 void XclImpXF::CreateUserStyle()
1176 if( IsStyleXF() && mbForceCreate
)
1180 void XclImpXF::ApplyPattern(
1181 SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
,
1182 SCTAB nScTab
, ULONG nForceScNumFmt
)
1184 // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1185 const ScPatternAttr
& rPattern
= CreatePattern();
1187 // insert into document
1188 ScDocument
& rDoc
= GetDoc();
1189 if( IsCellXF() && mpStyleSheet
)
1190 rDoc
.ApplyStyleAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, *mpStyleSheet
);
1191 if( HasUsedFlags() )
1192 rDoc
.ApplyPatternAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, rPattern
);
1194 // #108770# apply special number format
1195 if( nForceScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1197 ScPatternAttr
aPattern( GetDoc().GetPool() );
1198 GetNumFmtBuffer().FillScFmtToItemSet( aPattern
.GetItemSet(), nForceScNumFmt
);
1199 rDoc
.ApplyPatternAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, aPattern
);
1203 void XclImpXF::SetUsedFlags( sal_uInt8 nUsedFlags
)
1205 /* Notes about finding the mb***Used flags:
1206 - In cell XFs a *set* bit means a used attribute.
1207 - In style XFs a *cleared* bit means a used attribute.
1208 The mb***Used members always store true, if the attribute is used.
1209 The "mbCellXF == ::get_flag(...)" construct evaluates to true in
1210 both mentioned cases: cell XF and set bit; or style XF and cleared bit.
1212 mbProtUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_PROT
));
1213 mbFontUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_FONT
));
1214 mbFmtUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_VALFMT
));
1215 mbAlignUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_ALIGN
));
1216 mbBorderUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_BORDER
));
1217 mbAreaUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_AREA
));
1220 void XclImpXF::UpdateUsedFlags( const XclImpXF
& rParentXF
)
1222 /* Enables mb***Used flags, if the formatting attributes differ from
1223 the passed XF record. In cell XFs Excel uses the cell attributes,
1224 if they differ from the parent style XF.
1225 #109899# ...or if the respective flag is not set in parent style XF. */
1227 mbProtUsed
= !rParentXF
.mbProtUsed
|| !(maProtection
== rParentXF
.maProtection
);
1229 mbFontUsed
= !rParentXF
.mbFontUsed
|| (mnXclFont
!= rParentXF
.mnXclFont
);
1231 mbFmtUsed
= !rParentXF
.mbFmtUsed
|| (mnXclNumFmt
!= rParentXF
.mnXclNumFmt
);
1233 mbAlignUsed
= !rParentXF
.mbAlignUsed
|| !(maAlignment
== rParentXF
.maAlignment
);
1235 mbBorderUsed
= !rParentXF
.mbBorderUsed
|| !(maBorder
== rParentXF
.maBorder
);
1237 mbAreaUsed
= !rParentXF
.mbAreaUsed
|| !(maArea
== rParentXF
.maArea
);
1240 const ScPatternAttr
& XclImpXF::CreatePattern( bool bSkipPoolDefs
)
1242 if( mpPattern
.get() )
1245 // create new pattern attribute set
1246 mpPattern
.reset( new ScPatternAttr( GetDoc().GetPool() ) );
1247 SfxItemSet
& rItemSet
= mpPattern
->GetItemSet();
1249 // parent cell style
1252 if( XclImpXF
* pParentXF
= GetXFBuffer().GetXF( mnParent
) )
1254 mpStyleSheet
= pParentXF
->CreateStyleSheet();
1255 UpdateUsedFlags( *pParentXF
);
1261 maProtection
.FillToItemSet( rItemSet
, bSkipPoolDefs
);
1265 GetFontBuffer().FillToItemSet( rItemSet
, EXC_FONTITEM_CELL
, mnXclFont
, bSkipPoolDefs
);
1270 GetNumFmtBuffer().FillToItemSet( rItemSet
, mnXclNumFmt
, bSkipPoolDefs
);
1271 // Trace occurrences of Windows date formats
1272 GetTracer().TraceDates( mnXclNumFmt
);
1277 maAlignment
.FillToItemSet( rItemSet
, GetFontBuffer().GetFont( mnXclFont
), bSkipPoolDefs
);
1282 maBorder
.FillToItemSet( rItemSet
, GetPalette(), bSkipPoolDefs
);
1283 GetTracer().TraceBorderLineStyle(maBorder
.mnLeftLine
> EXC_LINE_HAIR
||
1284 maBorder
.mnRightLine
> EXC_LINE_HAIR
|| maBorder
.mnTopLine
> EXC_LINE_HAIR
||
1285 maBorder
.mnBottomLine
> EXC_LINE_HAIR
);
1291 maArea
.FillToItemSet( rItemSet
, GetPalette(), bSkipPoolDefs
);
1292 GetTracer().TraceFillPattern(maArea
.mnPattern
!= EXC_PATT_NONE
&&
1293 maArea
.mnPattern
!= EXC_PATT_SOLID
);
1299 ScStyleSheet
* XclImpXF::CreateStyleSheet()
1301 if( !mpStyleSheet
&& maStyleName
.Len() ) // valid name implies style XF
1303 // there may be a user-defined "Default" - test on built-in too!
1304 bool bDefStyle
= mbWasBuiltIn
&& (maStyleName
== ScGlobal::GetRscString( STR_STYLENAME_STANDARD
));
1307 // set all flags to true to get all items in CreatePattern()
1308 SetAllUsedFlags( true );
1309 // use existing "Default" style sheet
1310 mpStyleSheet
= static_cast< ScStyleSheet
* >( GetStyleSheetPool().Find(
1311 ScGlobal::GetRscString( STR_STYLENAME_STANDARD
), SFX_STYLE_FAMILY_PARA
) );
1312 DBG_ASSERT( mpStyleSheet
, "XclImpXF::CreateStyleSheet - Default style not found" );
1316 /* mbWasBuiltIn==true forces renaming of equal-named user defined styles
1317 to be able to re-export built-in styles correctly. */
1318 mpStyleSheet
= &ScfTools::MakeCellStyleSheet( GetStyleSheetPool(), maStyleName
, mbWasBuiltIn
);
1321 // bDefStyle==true omits default pool items in CreatePattern()
1323 mpStyleSheet
->GetItemSet().Put( CreatePattern( bDefStyle
).GetItemSet() );
1325 return mpStyleSheet
;
1328 // ----------------------------------------------------------------------------
1330 XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot
& rRoot
) :
1335 void XclImpXFBuffer::Initialize()
1340 void XclImpXFBuffer::ReadXF( XclImpStream
& rStrm
)
1342 XclImpXF
* pXF
= new XclImpXF( GetRoot() );
1343 pXF
->ReadXF( rStrm
);
1344 maXFList
.Append( pXF
);
1346 if( (GetBiff() >= EXC_BIFF3
) && (maXFList
.Count() == 1) )
1347 // set the name of the "Default" cell style (always the first XF in an Excel file)
1348 pXF
->SetBuiltInStyleName( EXC_STYLE_NORMAL
, 0 );
1351 void XclImpXFBuffer::ReadStyle( XclImpStream
& rStrm
)
1353 DBG_ASSERT_BIFF( GetBiff() >= EXC_BIFF3
);
1355 sal_uInt16 nXFIndex
;
1358 XclImpXF
* pXF
= GetXF( nXFIndex
& EXC_STYLE_XFMASK
); // bits 0...11 are used for XF index
1359 if( pXF
&& pXF
->IsStyleXF() )
1361 if( ::get_flag( nXFIndex
, EXC_STYLE_BUILTIN
) ) // built-in styles
1363 sal_uInt8 nStyleId
, nLevel
;
1364 rStrm
>> nStyleId
>> nLevel
;
1365 pXF
->SetBuiltInStyleName( nStyleId
, nLevel
);
1367 else // user-defined styles
1370 if( GetBiff() <= EXC_BIFF5
)
1371 aStyleName
= rStrm
.ReadByteString( false ); // 8 bit length
1373 aStyleName
= rStrm
.ReadUniString();
1374 if( aStyleName
.Len() ) // #i1624# #i1768# ignore unnamed styles
1375 pXF
->SetStyleName( aStyleName
);
1380 sal_uInt16
XclImpXFBuffer::GetFontIndex( sal_uInt16 nXFIndex
) const
1382 const XclImpXF
* pXF
= GetXF( nXFIndex
);
1383 return pXF
? pXF
->GetFontIndex() : EXC_FONT_NOTFOUND
;
1386 const XclImpFont
* XclImpXFBuffer::GetFont( sal_uInt16 nXFIndex
) const
1388 return GetFontBuffer().GetFont( GetFontIndex( nXFIndex
) );
1391 void XclImpXFBuffer::CreateUserStyles()
1393 for( XclImpXF
* pXF
= maXFList
.First(); pXF
; pXF
= maXFList
.Next() )
1394 pXF
->CreateUserStyle();
1397 void XclImpXFBuffer::ApplyPattern(
1398 SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
,
1399 SCTAB nScTab
, const XclImpXFIndex
& rXFIndex
)
1401 if( XclImpXF
* pXF
= GetXF( rXFIndex
.GetXFIndex() ) )
1403 // #108770# set 'Standard' number format for all Boolean cells
1404 ULONG nForceScNumFmt
= rXFIndex
.IsBoolCell() ? GetNumFmtBuffer().GetStdScNumFmt() : NUMBERFORMAT_ENTRY_NOT_FOUND
;
1405 pXF
->ApplyPattern( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, nForceScNumFmt
);
1409 // Buffer for XF indexes in cells =============================================
1411 IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange
, 100, 500 )
1413 bool XclImpXFRange::Expand( SCROW nScRow
, const XclImpXFIndex
& rXFIndex
)
1415 if( maXFIndex
!= rXFIndex
)
1418 if( mnScRow2
+ 1 == nScRow
)
1423 if( mnScRow1
> 0 && (mnScRow1
- 1 == nScRow
) )
1432 bool XclImpXFRange::Expand( const XclImpXFRange
& rNextRange
)
1434 DBG_ASSERT( mnScRow2
< rNextRange
.mnScRow1
, "XclImpXFRange::Expand - rows out of order" );
1435 if( (maXFIndex
== rNextRange
.maXFIndex
) && (mnScRow2
+ 1 == rNextRange
.mnScRow1
) )
1437 mnScRow2
= rNextRange
.mnScRow2
;
1443 // ----------------------------------------------------------------------------
1445 void XclImpXFRangeColumn::SetDefaultXF( const XclImpXFIndex
& rXFIndex
)
1447 // List should be empty when inserting the default column format.
1448 // Later explicit SetXF() calls will break up this range.
1449 DBG_ASSERT( maIndexList
.Empty(), "XclImpXFRangeColumn::SetDefaultXF - Setting Default Column XF is not empty" );
1451 // insert a complete row range with one insert.
1452 maIndexList
.Append( new XclImpXFRange( 0, MAXROW
, rXFIndex
) );
1455 // ----------------------------------------------------------------------------
1457 void XclImpXFRangeColumn::SetXF( SCROW nScRow
, const XclImpXFIndex
& rXFIndex
)
1459 XclImpXFRange
* pPrevRange
;
1460 XclImpXFRange
* pNextRange
;
1463 Find( pPrevRange
, pNextRange
, nNextIndex
, nScRow
);
1466 // try to overwrite XF (if row is contained in) or try to expand range
1469 if( pPrevRange
->Contains( nScRow
) ) // overwrite old XF
1471 if( rXFIndex
== pPrevRange
->maXFIndex
)
1474 SCROW nFirstScRow
= pPrevRange
->mnScRow1
;
1475 SCROW nLastScRow
= pPrevRange
->mnScRow2
;
1476 ULONG nIndex
= nNextIndex
- 1;
1477 XclImpXFRange
* pThisRange
= pPrevRange
;
1478 pPrevRange
= nIndex
? maIndexList
.GetObject( nIndex
- 1 ) : 0;
1480 if( nFirstScRow
== nLastScRow
) // replace solely XF
1482 pThisRange
->maXFIndex
= rXFIndex
;
1483 TryConcatPrev( nNextIndex
); // try to concat. next with this
1484 TryConcatPrev( nIndex
); // try to concat. this with previous
1486 else if( nFirstScRow
== nScRow
) // replace first XF
1488 ++(pThisRange
->mnScRow1
);
1489 // try to concatenate with previous of this
1490 if( !pPrevRange
|| !pPrevRange
->Expand( nScRow
, rXFIndex
) )
1491 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nIndex
);
1493 else if( nLastScRow
== nScRow
) // replace last XF
1495 --(pThisRange
->mnScRow2
);
1496 if( !pNextRange
|| !pNextRange
->Expand( nScRow
, rXFIndex
) )
1497 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nNextIndex
);
1499 else // insert in the middle of the range
1501 pThisRange
->mnScRow1
= nScRow
+ 1;
1502 // List::Insert() moves entries towards end of list, so insert twice at nIndex
1503 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nIndex
);
1504 maIndexList
.Insert( new XclImpXFRange( nFirstScRow
, nScRow
- 1, pThisRange
->maXFIndex
), nIndex
);
1508 else if( pPrevRange
->Expand( nScRow
, rXFIndex
) ) // try to expand
1510 TryConcatPrev( nNextIndex
); // try to concatenate next with expanded
1515 // try to expand next range
1516 if( pNextRange
&& pNextRange
->Expand( nScRow
, rXFIndex
) )
1520 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nNextIndex
);
1523 void XclImpXFRangeColumn::Find(
1524 XclImpXFRange
*& rpPrevRange
, XclImpXFRange
*& rpNextRange
,
1525 ULONG
& rnNextIndex
, SCROW nScRow
) const
1528 // test whether list is empty
1529 if( maIndexList
.Empty() )
1531 rpPrevRange
= rpNextRange
= 0;
1536 rpPrevRange
= maIndexList
.GetObject( 0 );
1537 rpNextRange
= maIndexList
.GetObject( maIndexList
.Count() - 1 );
1539 // test whether row is at end of list (contained in or behind last range)
1540 // rpPrevRange will contain a possible existing row
1541 if( rpNextRange
->mnScRow1
<= nScRow
)
1543 rpPrevRange
= rpNextRange
;
1545 rnNextIndex
= maIndexList
.Count();
1549 // test whether row is at beginning of list (really before first range)
1550 if( nScRow
< rpPrevRange
->mnScRow1
)
1552 rpNextRange
= rpPrevRange
;
1558 // loop: find range entries before and after new row
1559 // break the loop if there is no more range between first and last -or-
1560 // if rpPrevRange contains nScRow (rpNextRange will never contain nScRow)
1561 ULONG nPrevIndex
= 0;
1563 rnNextIndex
= maIndexList
.Count() - 1;
1564 XclImpXFRange
* pMidRange
;
1565 while( ((rnNextIndex
- nPrevIndex
) > 1) && (rpPrevRange
->mnScRow2
< nScRow
) )
1567 nMidIndex
= (nPrevIndex
+ rnNextIndex
) / 2;
1568 pMidRange
= maIndexList
.GetObject( nMidIndex
);
1569 DBG_ASSERT( pMidRange
, "XclImpXFRangeColumn::Find - missing XF index range" );
1570 if( nScRow
< pMidRange
->mnScRow1
) // row is really before pMidRange
1572 rpNextRange
= pMidRange
;
1573 rnNextIndex
= nMidIndex
;
1575 else // row is in or after pMidRange
1577 rpPrevRange
= pMidRange
;
1578 nPrevIndex
= nMidIndex
;
1582 // find next rpNextRange if rpPrevRange contains nScRow
1583 if( nScRow
<= rpPrevRange
->mnScRow2
)
1585 rnNextIndex
= nPrevIndex
+ 1;
1586 rpNextRange
= maIndexList
.GetObject( rnNextIndex
);
1590 void XclImpXFRangeColumn::TryConcatPrev( ULONG nIndex
)
1595 XclImpXFRange
* pPrevRange
= maIndexList
.GetObject( nIndex
- 1 );
1596 XclImpXFRange
* pNextRange
= maIndexList
.GetObject( nIndex
);
1597 if( !pPrevRange
|| !pNextRange
)
1600 if( pPrevRange
->Expand( *pNextRange
) )
1601 maIndexList
.Delete( nIndex
);
1604 // ----------------------------------------------------------------------------
1606 XclImpXFRangeBuffer::XclImpXFRangeBuffer( const XclImpRoot
& rRoot
) :
1611 XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1615 void XclImpXFRangeBuffer::Initialize()
1618 maHyperlinks
.clear();
1619 maMergeList
.RemoveAll();
1622 void XclImpXFRangeBuffer::SetXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
, XclImpXFInsertMode eMode
)
1624 SCCOL nScCol
= rScPos
.Col();
1625 SCROW nScRow
= rScPos
.Row();
1628 size_t nIndex
= static_cast< size_t >( nScCol
);
1629 if( maColumns
.size() <= nIndex
)
1630 maColumns
.resize( nIndex
+ 1 );
1631 if( !maColumns
[ nIndex
] )
1632 maColumns
[ nIndex
].reset( new XclImpXFRangeColumn
);
1633 // #108770# remember all Boolean cells, they will get 'Standard' number format
1634 maColumns
[ nIndex
]->SetXF( nScRow
, XclImpXFIndex( nXFIndex
, eMode
== xlXFModeBoolCell
) );
1636 // set "center across selection" and "fill" attribute for all following empty cells
1637 // #97130# ignore it on row default XFs
1638 if( eMode
!= xlXFModeRow
)
1640 const XclImpXF
* pXF
= GetXFBuffer().GetXF( nXFIndex
);
1641 if( pXF
&& ((pXF
->GetHorAlign() == EXC_XF_HOR_CENTER_AS
) || (pXF
->GetHorAlign() == EXC_XF_HOR_FILL
)) )
1643 // expand last merged range if this attribute is set repeatedly
1644 ScRange
* pRange
= maMergeList
.Last();
1645 if( pRange
&& (pRange
->aEnd
.Row() == nScRow
) && (pRange
->aEnd
.Col() + 1 == nScCol
)
1646 && (eMode
== xlXFModeBlank
) )
1647 pRange
->aEnd
.IncCol();
1648 else if( eMode
!= xlXFModeBlank
) // #108781# do not merge empty cells
1649 SetMerge( nScCol
, nScRow
);
1654 void XclImpXFRangeBuffer::SetXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1656 SetXF( rScPos
, nXFIndex
, xlXFModeCell
);
1659 void XclImpXFRangeBuffer::SetBlankXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1661 SetXF( rScPos
, nXFIndex
, xlXFModeBlank
);
1664 void XclImpXFRangeBuffer::SetBoolXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1666 SetXF( rScPos
, nXFIndex
, xlXFModeBoolCell
);
1669 void XclImpXFRangeBuffer::SetRowDefXF( SCROW nScRow
, sal_uInt16 nXFIndex
)
1671 for( SCCOL nScCol
= 0; nScCol
<= MAXCOL
; ++nScCol
)
1672 SetXF( ScAddress( nScCol
, nScRow
, 0 ), nXFIndex
, xlXFModeRow
);
1675 void XclImpXFRangeBuffer::SetColumnDefXF( SCCOL nScCol
, sal_uInt16 nXFIndex
)
1677 // our array should not have values when creating the default column format.
1678 size_t nIndex
= static_cast< size_t >( nScCol
);
1679 if( maColumns
.size() <= nIndex
)
1680 maColumns
.resize( nIndex
+ 1 );
1681 DBG_ASSERT( !maColumns
[ nIndex
], "XclImpXFRangeBuffer::SetColumnDefXF - default column of XFs already has values" );
1682 maColumns
[ nIndex
].reset( new XclImpXFRangeColumn
);
1683 maColumns
[ nIndex
]->SetDefaultXF( XclImpXFIndex( nXFIndex
) );
1686 void XclImpXFRangeBuffer::SetBorderLine( const ScRange
& rRange
, SCTAB nScTab
, USHORT nLine
)
1688 SCCOL nFromScCol
= (nLine
== BOX_LINE_RIGHT
) ? rRange
.aEnd
.Col() : rRange
.aStart
.Col();
1689 SCROW nFromScRow
= (nLine
== BOX_LINE_BOTTOM
) ? rRange
.aEnd
.Row() : rRange
.aStart
.Row();
1690 ScDocument
& rDoc
= GetDoc();
1692 const SvxBoxItem
* pFromItem
= static_cast< const SvxBoxItem
* >(
1693 rDoc
.GetAttr( nFromScCol
, nFromScRow
, nScTab
, ATTR_BORDER
) );
1694 const SvxBoxItem
* pToItem
= static_cast< const SvxBoxItem
* >(
1695 rDoc
.GetAttr( rRange
.aStart
.Col(), rRange
.aStart
.Row(), nScTab
, ATTR_BORDER
) );
1697 SvxBoxItem
aNewItem( *pToItem
);
1698 aNewItem
.SetLine( pFromItem
->GetLine( nLine
), nLine
);
1699 rDoc
.ApplyAttr( rRange
.aStart
.Col(), rRange
.aStart
.Row(), nScTab
, aNewItem
);
1702 void XclImpXFRangeBuffer::SetHyperlink( const XclRange
& rXclRange
, const String
& rUrl
)
1704 maHyperlinks
.push_back( XclImpHyperlinkRange( rXclRange
, rUrl
) );
1707 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol
, SCROW nScRow
)
1709 maMergeList
.Append( ScRange( nScCol
, nScRow
, 0 ) );
1712 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
)
1714 if( (nScCol1
< nScCol2
) || (nScRow1
< nScRow2
) )
1715 maMergeList
.Append( ScRange( nScCol1
, nScRow1
, 0, nScCol2
, nScRow2
, 0 ) );
1718 void XclImpXFRangeBuffer::Finalize()
1720 ScDocument
& rDoc
= GetDoc();
1721 SCTAB nScTab
= GetCurrScTab();
1724 XclImpXFBuffer
& rXFBuffer
= GetXFBuffer();
1725 for( XclImpXFRangeColumnVec::const_iterator aVBeg
= maColumns
.begin(), aVEnd
= maColumns
.end(), aVIt
= aVBeg
; aVIt
!= aVEnd
; ++aVIt
)
1727 // apply all cell styles of an existing column
1730 XclImpXFRangeColumn
& rColumn
= **aVIt
;
1731 SCCOL nScCol
= static_cast< SCCOL
>( aVIt
- aVBeg
);
1732 for( XclImpXFRange
* pStyle
= rColumn
.First(); pStyle
; pStyle
= rColumn
.Next() )
1733 rXFBuffer
.ApplyPattern( nScCol
, pStyle
->mnScRow1
, nScCol
, pStyle
->mnScRow2
, nScTab
, pStyle
->maXFIndex
);
1737 // insert hyperlink cells
1738 for( XclImpHyperlinkList::const_iterator aLIt
= maHyperlinks
.begin(), aLEnd
= maHyperlinks
.end(); aLIt
!= aLEnd
; ++aLIt
)
1739 XclImpHyperlink::InsertUrl( GetRoot(), aLIt
->first
, aLIt
->second
);
1741 // apply cell merging
1742 for( const ScRange
* pRange
= maMergeList
.First(); pRange
; pRange
= maMergeList
.Next() )
1744 const ScAddress
& rStart
= pRange
->aStart
;
1745 const ScAddress
& rEnd
= pRange
->aEnd
;
1746 bool bMultiCol
= rStart
.Col() != rEnd
.Col();
1747 bool bMultiRow
= rStart
.Row() != rEnd
.Row();
1748 // set correct right border
1750 SetBorderLine( *pRange
, nScTab
, BOX_LINE_RIGHT
);
1751 // set correct lower border
1753 SetBorderLine( *pRange
, nScTab
, BOX_LINE_BOTTOM
);
1755 if( bMultiCol
|| bMultiRow
)
1756 rDoc
.DoMerge( nScTab
, rStart
.Col(), rStart
.Row(), rEnd
.Col(), rEnd
.Row() );
1757 // #i93609# merged range in a single row: test if manual row height is needed
1760 bool bTextWrap
= static_cast< const SfxBoolItem
* >( rDoc
.GetAttr( rStart
.Col(), rStart
.Row(), rStart
.Tab(), ATTR_LINEBREAK
) )->GetValue();
1761 if( !bTextWrap
&& (rDoc
.GetCellType( rStart
) == CELLTYPE_EDIT
) )
1762 if( const EditTextObject
* pEditObj
= static_cast< const ScEditCell
* >( rDoc
.GetCell( rStart
) )->GetData() )
1763 bTextWrap
= pEditObj
->GetParagraphCount() > 1;
1765 GetOldRoot().pColRowBuff
->SetManualRowHeight( rStart
.Row() );
1770 // ============================================================================