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
),
1036 XclImpXF::~XclImpXF()
1040 void XclImpXF::ReadXF2( XclImpStream
& rStrm
)
1042 sal_uInt8 nReadFont
, nReadNumFmt
, nFlags
;
1045 rStrm
>> nReadNumFmt
>> nFlags
;
1047 // XF type always cell, no parent, used flags always true
1048 SetAllUsedFlags( true );
1051 maProtection
.FillFromXF2( nReadNumFmt
);
1052 mnXclFont
= nReadFont
;
1053 mnXclNumFmt
= nReadNumFmt
& EXC_XF2_VALFMT_MASK
;
1054 maAlignment
.FillFromXF2( nFlags
);
1055 maBorder
.FillFromXF2( nFlags
);
1056 maArea
.FillFromXF2( nFlags
);
1059 void XclImpXF::ReadXF3( XclImpStream
& rStrm
)
1062 sal_uInt16 nTypeProt
, nAlign
, nArea
;
1063 sal_uInt8 nReadFont
, nReadNumFmt
;
1064 rStrm
>> nReadFont
>> nReadNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1066 // XF type/parent, attribute used flags
1067 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
); // new in BIFF3
1068 mnParent
= ::extract_value
< sal_uInt16
>( nAlign
, 4, 12 ); // new in BIFF3
1069 SetUsedFlags( ::extract_value
< sal_uInt8
>( nTypeProt
, 10, 6 ) );
1072 maProtection
.FillFromXF3( nTypeProt
);
1073 mnXclFont
= nReadFont
;
1074 mnXclNumFmt
= nReadNumFmt
;
1075 maAlignment
.FillFromXF3( nAlign
);
1076 maBorder
.FillFromXF3( nBorder
);
1077 maArea
.FillFromXF3( nArea
); // new in BIFF3
1080 void XclImpXF::ReadXF4( XclImpStream
& rStrm
)
1083 sal_uInt16 nTypeProt
, nAlign
, nArea
;
1084 sal_uInt8 nReadFont
, nReadNumFmt
;
1085 rStrm
>> nReadFont
>> nReadNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1087 // XF type/parent, attribute used flags
1088 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1089 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1090 SetUsedFlags( ::extract_value
< sal_uInt8
>( nAlign
, 10, 6 ) );
1093 maProtection
.FillFromXF3( nTypeProt
);
1094 mnXclFont
= nReadFont
;
1095 mnXclNumFmt
= nReadNumFmt
;
1096 maAlignment
.FillFromXF4( nAlign
);
1097 maBorder
.FillFromXF3( nBorder
);
1098 maArea
.FillFromXF3( nArea
);
1101 void XclImpXF::ReadXF5( XclImpStream
& rStrm
)
1103 sal_uInt32 nArea
, nBorder
;
1104 sal_uInt16 nTypeProt
, nAlign
;
1105 rStrm
>> mnXclFont
>> mnXclNumFmt
>> nTypeProt
>> nAlign
>> nArea
>> nBorder
;
1107 // XF type/parent, attribute used flags
1108 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1109 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1110 SetUsedFlags( ::extract_value
< sal_uInt8
>( nAlign
, 10, 6 ) );
1113 maProtection
.FillFromXF3( nTypeProt
);
1114 maAlignment
.FillFromXF5( nAlign
);
1115 maBorder
.FillFromXF5( nBorder
, nArea
);
1116 maArea
.FillFromXF5( nArea
);
1119 void XclImpXF::ReadXF8( XclImpStream
& rStrm
)
1121 sal_uInt32 nBorder1
, nBorder2
;
1122 sal_uInt16 nTypeProt
, nAlign
, nMiscAttrib
, nArea
;
1123 rStrm
>> mnXclFont
>> mnXclNumFmt
>> nTypeProt
>> nAlign
>> nMiscAttrib
>> nBorder1
>> nBorder2
>> nArea
;
1125 // XF type/parent, attribute used flags
1126 mbCellXF
= !::get_flag( nTypeProt
, EXC_XF_STYLE
);
1127 mnParent
= ::extract_value
< sal_uInt16
>( nTypeProt
, 4, 12 );
1128 SetUsedFlags( ::extract_value
< sal_uInt8
>( nMiscAttrib
, 10, 6 ) );
1131 maProtection
.FillFromXF3( nTypeProt
);
1132 maAlignment
.FillFromXF8( nAlign
, nMiscAttrib
);
1133 maBorder
.FillFromXF8( nBorder1
, nBorder2
);
1134 maArea
.FillFromXF8( nBorder2
, nArea
);
1137 void XclImpXF::ReadXF( XclImpStream
& rStrm
)
1141 case EXC_BIFF2
: ReadXF2( rStrm
); break;
1142 case EXC_BIFF3
: ReadXF3( rStrm
); break;
1143 case EXC_BIFF4
: ReadXF4( rStrm
); break;
1144 case EXC_BIFF5
: ReadXF5( rStrm
); break;
1145 case EXC_BIFF8
: ReadXF8( rStrm
); break;
1146 default: DBG_ERROR_BIFF();
1150 const ScPatternAttr
& XclImpXF::CreatePattern( bool bSkipPoolDefs
)
1152 if( mpPattern
.get() )
1155 // create new pattern attribute set
1156 mpPattern
.reset( new ScPatternAttr( GetDoc().GetPool() ) );
1157 SfxItemSet
& rItemSet
= mpPattern
->GetItemSet();
1159 // parent cell style
1160 if( IsCellXF() && !mpStyleSheet
)
1162 mpStyleSheet
= GetXFBuffer().CreateStyleSheet( mnParent
);
1163 if( XclImpXF
* pParentXF
= GetXFBuffer().GetXF( mnParent
) )
1164 UpdateUsedFlags( *pParentXF
);
1169 maProtection
.FillToItemSet( rItemSet
, bSkipPoolDefs
);
1173 GetFontBuffer().FillToItemSet( rItemSet
, EXC_FONTITEM_CELL
, mnXclFont
, bSkipPoolDefs
);
1178 GetNumFmtBuffer().FillToItemSet( rItemSet
, mnXclNumFmt
, bSkipPoolDefs
);
1179 // Trace occurrences of Windows date formats
1180 GetTracer().TraceDates( mnXclNumFmt
);
1185 maAlignment
.FillToItemSet( rItemSet
, GetFontBuffer().GetFont( mnXclFont
), bSkipPoolDefs
);
1190 maBorder
.FillToItemSet( rItemSet
, GetPalette(), bSkipPoolDefs
);
1191 GetTracer().TraceBorderLineStyle(maBorder
.mnLeftLine
> EXC_LINE_HAIR
||
1192 maBorder
.mnRightLine
> EXC_LINE_HAIR
|| maBorder
.mnTopLine
> EXC_LINE_HAIR
||
1193 maBorder
.mnBottomLine
> EXC_LINE_HAIR
);
1199 maArea
.FillToItemSet( rItemSet
, GetPalette(), bSkipPoolDefs
);
1200 GetTracer().TraceFillPattern(maArea
.mnPattern
!= EXC_PATT_NONE
&&
1201 maArea
.mnPattern
!= EXC_PATT_SOLID
);
1207 void XclImpXF::ApplyPattern(
1208 SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
,
1209 SCTAB nScTab
, ULONG nForceScNumFmt
)
1211 // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1212 const ScPatternAttr
& rPattern
= CreatePattern();
1214 // insert into document
1215 ScDocument
& rDoc
= GetDoc();
1216 if( IsCellXF() && mpStyleSheet
)
1217 rDoc
.ApplyStyleAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, *mpStyleSheet
);
1218 if( HasUsedFlags() )
1219 rDoc
.ApplyPatternAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, rPattern
);
1221 // #108770# apply special number format
1222 if( nForceScNumFmt
!= NUMBERFORMAT_ENTRY_NOT_FOUND
)
1224 ScPatternAttr
aPattern( GetDoc().GetPool() );
1225 GetNumFmtBuffer().FillScFmtToItemSet( aPattern
.GetItemSet(), nForceScNumFmt
);
1226 rDoc
.ApplyPatternAreaTab( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, aPattern
);
1230 void XclImpXF::SetUsedFlags( sal_uInt8 nUsedFlags
)
1232 /* Notes about finding the mb***Used flags:
1233 - In cell XFs a *set* bit means a used attribute.
1234 - In style XFs a *cleared* bit means a used attribute.
1235 The mb***Used members always store true, if the attribute is used.
1236 The "mbCellXF == ::get_flag(...)" construct evaluates to true in
1237 both mentioned cases: cell XF and set bit; or style XF and cleared bit.
1239 mbProtUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_PROT
));
1240 mbFontUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_FONT
));
1241 mbFmtUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_VALFMT
));
1242 mbAlignUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_ALIGN
));
1243 mbBorderUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_BORDER
));
1244 mbAreaUsed
= (mbCellXF
== ::get_flag( nUsedFlags
, EXC_XF_DIFF_AREA
));
1247 void XclImpXF::UpdateUsedFlags( const XclImpXF
& rParentXF
)
1249 /* Enables mb***Used flags, if the formatting attributes differ from
1250 the passed XF record. In cell XFs Excel uses the cell attributes,
1251 if they differ from the parent style XF.
1252 #109899# ...or if the respective flag is not set in parent style XF. */
1254 mbProtUsed
= !rParentXF
.mbProtUsed
|| !(maProtection
== rParentXF
.maProtection
);
1256 mbFontUsed
= !rParentXF
.mbFontUsed
|| (mnXclFont
!= rParentXF
.mnXclFont
);
1258 mbFmtUsed
= !rParentXF
.mbFmtUsed
|| (mnXclNumFmt
!= rParentXF
.mnXclNumFmt
);
1260 mbAlignUsed
= !rParentXF
.mbAlignUsed
|| !(maAlignment
== rParentXF
.maAlignment
);
1262 mbBorderUsed
= !rParentXF
.mbBorderUsed
|| !(maBorder
== rParentXF
.maBorder
);
1264 mbAreaUsed
= !rParentXF
.mbAreaUsed
|| !(maArea
== rParentXF
.maArea
);
1267 // ----------------------------------------------------------------------------
1269 XclImpStyle::XclImpStyle( const XclImpRoot
& rRoot
) :
1270 XclImpRoot( rRoot
),
1271 mnXfId( EXC_XF_NOTFOUND
),
1272 mnBuiltinId( EXC_STYLE_USERDEF
),
1273 mnLevel( EXC_STYLE_NOLEVEL
),
1281 void XclImpStyle::ReadStyle( XclImpStream
& rStrm
)
1283 DBG_ASSERT_BIFF( GetBiff() >= EXC_BIFF3
);
1285 sal_uInt16 nXFIndex
;
1287 mnXfId
= nXFIndex
& EXC_STYLE_XFMASK
;
1288 mbBuiltin
= ::get_flag( nXFIndex
, EXC_STYLE_BUILTIN
);
1292 rStrm
>> mnBuiltinId
>> mnLevel
;
1296 maName
= (GetBiff() <= EXC_BIFF5
) ? rStrm
.ReadByteString( false ) : rStrm
.ReadUniString();
1297 // #i103281# check if this is a new built-in style introduced in XL2007
1298 if( (GetBiff() == EXC_BIFF8
) && (rStrm
.GetNextRecId() == EXC_ID_STYLEEXT
) && rStrm
.StartNextRecord() )
1300 sal_uInt8 nExtFlags
;
1303 mbBuiltin
= ::get_flag( nExtFlags
, EXC_STYLEEXT_BUILTIN
);
1304 mbCustom
= ::get_flag( nExtFlags
, EXC_STYLEEXT_CUSTOM
);
1305 mbHidden
= ::get_flag( nExtFlags
, EXC_STYLEEXT_HIDDEN
);
1308 rStrm
.Ignore( 1 ); // category
1309 rStrm
>> mnBuiltinId
>> mnLevel
;
1315 ScStyleSheet
* XclImpStyle::CreateStyleSheet()
1317 // #i1624# #i1768# ignore unnamed user styles
1318 if( !mpStyleSheet
&& (maFinalName
.Len() > 0) )
1320 bool bCreatePattern
= false;
1321 XclImpXF
* pXF
= GetXFBuffer().GetXF( mnXfId
);
1323 bool bDefStyle
= mbBuiltin
&& (mnBuiltinId
== EXC_STYLE_NORMAL
);
1326 // set all flags to true to get all items in XclImpXF::CreatePattern()
1327 if( pXF
) pXF
->SetAllUsedFlags( true );
1328 // use existing "Default" style sheet
1329 mpStyleSheet
= static_cast< ScStyleSheet
* >( GetStyleSheetPool().Find(
1330 ScGlobal::GetRscString( STR_STYLENAME_STANDARD
), SFX_STYLE_FAMILY_PARA
) );
1331 DBG_ASSERT( mpStyleSheet
, "XclImpStyle::CreateStyleSheet - Default style not found" );
1332 bCreatePattern
= true;
1336 /* #i103281# do not create another style sheet of the same name,
1337 if it exists already. This is needed to prevent that styles
1338 pasted from clipboard get duplicated over and over. */
1339 mpStyleSheet
= static_cast< ScStyleSheet
* >( GetStyleSheetPool().Find( maFinalName
, SFX_STYLE_FAMILY_PARA
) );
1342 mpStyleSheet
= &static_cast< ScStyleSheet
& >( GetStyleSheetPool().Make( maFinalName
, SFX_STYLE_FAMILY_PARA
, SFXSTYLEBIT_USERDEF
) );
1343 bCreatePattern
= true;
1347 // bDefStyle==true omits default pool items in CreatePattern()
1348 if( bCreatePattern
&& mpStyleSheet
&& pXF
)
1349 mpStyleSheet
->GetItemSet().Put( pXF
->CreatePattern( bDefStyle
).GetItemSet() );
1351 return mpStyleSheet
;
1354 void XclImpStyle::CreateUserStyle( const String
& rFinalName
)
1356 maFinalName
= rFinalName
;
1357 if( !IsBuiltin() || mbCustom
)
1361 // ----------------------------------------------------------------------------
1363 XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot
& rRoot
) :
1368 void XclImpXFBuffer::Initialize()
1371 maBuiltinStyles
.Clear();
1372 maUserStyles
.Clear();
1373 maStylesByXf
.clear();
1376 void XclImpXFBuffer::ReadXF( XclImpStream
& rStrm
)
1378 XclImpXF
* pXF
= new XclImpXF( GetRoot() );
1379 pXF
->ReadXF( rStrm
);
1380 maXFList
.Append( pXF
);
1383 void XclImpXFBuffer::ReadStyle( XclImpStream
& rStrm
)
1385 XclImpStyle
* pStyle
= new XclImpStyle( GetRoot() );
1386 pStyle
->ReadStyle( rStrm
);
1387 (pStyle
->IsBuiltin() ? maBuiltinStyles
: maUserStyles
).Append( pStyle
);
1388 DBG_ASSERT( maStylesByXf
.count( pStyle
->GetXfId() ) == 0, "XclImpXFBuffer::ReadStyle - multiple styles with equal XF identifier" );
1389 maStylesByXf
[ pStyle
->GetXfId() ] = pStyle
;
1392 sal_uInt16
XclImpXFBuffer::GetFontIndex( sal_uInt16 nXFIndex
) const
1394 const XclImpXF
* pXF
= GetXF( nXFIndex
);
1395 return pXF
? pXF
->GetFontIndex() : EXC_FONT_NOTFOUND
;
1398 const XclImpFont
* XclImpXFBuffer::GetFont( sal_uInt16 nXFIndex
) const
1400 return GetFontBuffer().GetFont( GetFontIndex( nXFIndex
) );
1405 /** Functor for case-insensitive string comparison, usable in maps etc. */
1406 struct IgnoreCaseCompare
1408 inline bool operator()( const String
& rName1
, const String
& rName2
) const
1409 { return rName1
.CompareIgnoreCaseToAscii( rName2
) == COMPARE_LESS
; }
1414 void XclImpXFBuffer::CreateUserStyles()
1416 // calculate final names of all styles
1417 typedef ::std::map
< String
, XclImpStyle
*, IgnoreCaseCompare
> CellStyleNameMap
;
1418 typedef ::std::vector
< XclImpStyle
* > XclImpStyleVector
;
1420 CellStyleNameMap aCellStyles
;
1421 XclImpStyleVector aConflictNameStyles
;
1423 /* First, reserve style names that are built-in in Calc. This causes that
1424 imported cell styles get different unused names and thus do not try to
1425 overwrite these built-in styles. For BIFF4 workbooks (which contain a
1426 separate list of cell styles per sheet), reserve all existing styles if
1427 current sheet is not the first sheet (this styles buffer will be
1428 initialized again for every new sheet). This will create unique names
1429 for styles in different sheets with the same name. Assuming that the
1430 BIFF4W import filter is never used to import from clipboard... */
1431 bool bReserveAll
= (GetBiff() == EXC_BIFF4
) && (GetCurrScTab() > 0);
1432 SfxStyleSheetIterator
aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA
);
1433 String aStandardName
= ScGlobal::GetRscString( STR_STYLENAME_STANDARD
);
1434 for( SfxStyleSheetBase
* pStyleSheet
= aStyleIter
.First(); pStyleSheet
; pStyleSheet
= aStyleIter
.Next() )
1435 if( (pStyleSheet
->GetName() != aStandardName
) && (bReserveAll
|| !pStyleSheet
->IsUserDefined()) )
1436 if( aCellStyles
.count( pStyleSheet
->GetName() ) == 0 )
1437 aCellStyles
[ pStyleSheet
->GetName() ] = 0;
1439 /* Calculate names of built-in styles. Store styles with reserved names
1440 in the aConflictNameStyles list. */
1441 for( XclImpStyle
* pStyle
= maBuiltinStyles
.First(); pStyle
; pStyle
= maBuiltinStyles
.Next() )
1443 String aStyleName
= XclTools::GetBuiltInStyleName( pStyle
->GetBuiltinId(), pStyle
->GetName(), pStyle
->GetLevel() );
1444 DBG_ASSERT( bReserveAll
|| (aCellStyles
.count( aStyleName
) == 0),
1445 "XclImpXFBuffer::CreateUserStyles - multiple styles with equal built-in identifier" );
1446 if( aCellStyles
.count( aStyleName
) > 0 )
1447 aConflictNameStyles
.push_back( pStyle
);
1449 aCellStyles
[ aStyleName
] = pStyle
;
1452 /* Calculate names of user defined styles. Store styles with reserved
1453 names in the aConflictNameStyles list. */
1454 for( XclImpStyle
* pStyle
= maUserStyles
.First(); pStyle
; pStyle
= maUserStyles
.Next() )
1456 // #i1624# #i1768# ignore unnamed user styles
1457 if( pStyle
->GetName().Len() > 0 )
1459 if( aCellStyles
.count( pStyle
->GetName() ) > 0 )
1460 aConflictNameStyles
.push_back( pStyle
);
1462 aCellStyles
[ pStyle
->GetName() ] = pStyle
;
1466 // find unused names for all styles with conflicting names
1467 for( XclImpStyleVector::iterator aIt
= aConflictNameStyles
.begin(), aEnd
= aConflictNameStyles
.end(); aIt
!= aEnd
; ++aIt
)
1469 XclImpStyle
* pStyle
= *aIt
;
1471 sal_Int32 nIndex
= 0;
1474 aUnusedName
.Assign( pStyle
->GetName() ).Append( ' ' ).Append( String::CreateFromInt32( ++nIndex
) );
1476 while( aCellStyles
.count( aUnusedName
) > 0 );
1477 aCellStyles
[ aUnusedName
] = pStyle
;
1480 // set final names and create user-defined and modified built-in cell styles
1481 for( CellStyleNameMap::iterator aIt
= aCellStyles
.begin(), aEnd
= aCellStyles
.end(); aIt
!= aEnd
; ++aIt
)
1483 aIt
->second
->CreateUserStyle( aIt
->first
);
1486 ScStyleSheet
* XclImpXFBuffer::CreateStyleSheet( sal_uInt16 nXFIndex
)
1488 XclImpStyleMap::iterator aIt
= maStylesByXf
.find( nXFIndex
);
1489 return (aIt
== maStylesByXf
.end()) ? 0 : aIt
->second
->CreateStyleSheet();
1492 void XclImpXFBuffer::ApplyPattern(
1493 SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
,
1494 SCTAB nScTab
, const XclImpXFIndex
& rXFIndex
)
1496 if( XclImpXF
* pXF
= GetXF( rXFIndex
.GetXFIndex() ) )
1498 // #108770# set 'Standard' number format for all Boolean cells
1499 ULONG nForceScNumFmt
= rXFIndex
.IsBoolCell() ? GetNumFmtBuffer().GetStdScNumFmt() : NUMBERFORMAT_ENTRY_NOT_FOUND
;
1500 pXF
->ApplyPattern( nScCol1
, nScRow1
, nScCol2
, nScRow2
, nScTab
, nForceScNumFmt
);
1504 // Buffer for XF indexes in cells =============================================
1506 IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange
, 100, 500 )
1508 bool XclImpXFRange::Expand( SCROW nScRow
, const XclImpXFIndex
& rXFIndex
)
1510 if( maXFIndex
!= rXFIndex
)
1513 if( mnScRow2
+ 1 == nScRow
)
1518 if( mnScRow1
> 0 && (mnScRow1
- 1 == nScRow
) )
1527 bool XclImpXFRange::Expand( const XclImpXFRange
& rNextRange
)
1529 DBG_ASSERT( mnScRow2
< rNextRange
.mnScRow1
, "XclImpXFRange::Expand - rows out of order" );
1530 if( (maXFIndex
== rNextRange
.maXFIndex
) && (mnScRow2
+ 1 == rNextRange
.mnScRow1
) )
1532 mnScRow2
= rNextRange
.mnScRow2
;
1538 // ----------------------------------------------------------------------------
1540 void XclImpXFRangeColumn::SetDefaultXF( const XclImpXFIndex
& rXFIndex
)
1542 // List should be empty when inserting the default column format.
1543 // Later explicit SetXF() calls will break up this range.
1544 DBG_ASSERT( maIndexList
.Empty(), "XclImpXFRangeColumn::SetDefaultXF - Setting Default Column XF is not empty" );
1546 // insert a complete row range with one insert.
1547 maIndexList
.Append( new XclImpXFRange( 0, MAXROW
, rXFIndex
) );
1550 // ----------------------------------------------------------------------------
1552 void XclImpXFRangeColumn::SetXF( SCROW nScRow
, const XclImpXFIndex
& rXFIndex
)
1554 XclImpXFRange
* pPrevRange
;
1555 XclImpXFRange
* pNextRange
;
1558 Find( pPrevRange
, pNextRange
, nNextIndex
, nScRow
);
1561 // try to overwrite XF (if row is contained in) or try to expand range
1564 if( pPrevRange
->Contains( nScRow
) ) // overwrite old XF
1566 if( rXFIndex
== pPrevRange
->maXFIndex
)
1569 SCROW nFirstScRow
= pPrevRange
->mnScRow1
;
1570 SCROW nLastScRow
= pPrevRange
->mnScRow2
;
1571 ULONG nIndex
= nNextIndex
- 1;
1572 XclImpXFRange
* pThisRange
= pPrevRange
;
1573 pPrevRange
= nIndex
? maIndexList
.GetObject( nIndex
- 1 ) : 0;
1575 if( nFirstScRow
== nLastScRow
) // replace solely XF
1577 pThisRange
->maXFIndex
= rXFIndex
;
1578 TryConcatPrev( nNextIndex
); // try to concat. next with this
1579 TryConcatPrev( nIndex
); // try to concat. this with previous
1581 else if( nFirstScRow
== nScRow
) // replace first XF
1583 ++(pThisRange
->mnScRow1
);
1584 // try to concatenate with previous of this
1585 if( !pPrevRange
|| !pPrevRange
->Expand( nScRow
, rXFIndex
) )
1586 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nIndex
);
1588 else if( nLastScRow
== nScRow
) // replace last XF
1590 --(pThisRange
->mnScRow2
);
1591 if( !pNextRange
|| !pNextRange
->Expand( nScRow
, rXFIndex
) )
1592 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nNextIndex
);
1594 else // insert in the middle of the range
1596 pThisRange
->mnScRow1
= nScRow
+ 1;
1597 // List::Insert() moves entries towards end of list, so insert twice at nIndex
1598 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nIndex
);
1599 maIndexList
.Insert( new XclImpXFRange( nFirstScRow
, nScRow
- 1, pThisRange
->maXFIndex
), nIndex
);
1603 else if( pPrevRange
->Expand( nScRow
, rXFIndex
) ) // try to expand
1605 TryConcatPrev( nNextIndex
); // try to concatenate next with expanded
1610 // try to expand next range
1611 if( pNextRange
&& pNextRange
->Expand( nScRow
, rXFIndex
) )
1615 maIndexList
.Insert( new XclImpXFRange( nScRow
, rXFIndex
), nNextIndex
);
1618 void XclImpXFRangeColumn::Find(
1619 XclImpXFRange
*& rpPrevRange
, XclImpXFRange
*& rpNextRange
,
1620 ULONG
& rnNextIndex
, SCROW nScRow
) const
1623 // test whether list is empty
1624 if( maIndexList
.Empty() )
1626 rpPrevRange
= rpNextRange
= 0;
1631 rpPrevRange
= maIndexList
.GetObject( 0 );
1632 rpNextRange
= maIndexList
.GetObject( maIndexList
.Count() - 1 );
1634 // test whether row is at end of list (contained in or behind last range)
1635 // rpPrevRange will contain a possible existing row
1636 if( rpNextRange
->mnScRow1
<= nScRow
)
1638 rpPrevRange
= rpNextRange
;
1640 rnNextIndex
= maIndexList
.Count();
1644 // test whether row is at beginning of list (really before first range)
1645 if( nScRow
< rpPrevRange
->mnScRow1
)
1647 rpNextRange
= rpPrevRange
;
1653 // loop: find range entries before and after new row
1654 // break the loop if there is no more range between first and last -or-
1655 // if rpPrevRange contains nScRow (rpNextRange will never contain nScRow)
1656 ULONG nPrevIndex
= 0;
1658 rnNextIndex
= maIndexList
.Count() - 1;
1659 XclImpXFRange
* pMidRange
;
1660 while( ((rnNextIndex
- nPrevIndex
) > 1) && (rpPrevRange
->mnScRow2
< nScRow
) )
1662 nMidIndex
= (nPrevIndex
+ rnNextIndex
) / 2;
1663 pMidRange
= maIndexList
.GetObject( nMidIndex
);
1664 DBG_ASSERT( pMidRange
, "XclImpXFRangeColumn::Find - missing XF index range" );
1665 if( nScRow
< pMidRange
->mnScRow1
) // row is really before pMidRange
1667 rpNextRange
= pMidRange
;
1668 rnNextIndex
= nMidIndex
;
1670 else // row is in or after pMidRange
1672 rpPrevRange
= pMidRange
;
1673 nPrevIndex
= nMidIndex
;
1677 // find next rpNextRange if rpPrevRange contains nScRow
1678 if( nScRow
<= rpPrevRange
->mnScRow2
)
1680 rnNextIndex
= nPrevIndex
+ 1;
1681 rpNextRange
= maIndexList
.GetObject( rnNextIndex
);
1685 void XclImpXFRangeColumn::TryConcatPrev( ULONG nIndex
)
1690 XclImpXFRange
* pPrevRange
= maIndexList
.GetObject( nIndex
- 1 );
1691 XclImpXFRange
* pNextRange
= maIndexList
.GetObject( nIndex
);
1692 if( !pPrevRange
|| !pNextRange
)
1695 if( pPrevRange
->Expand( *pNextRange
) )
1696 maIndexList
.Delete( nIndex
);
1699 // ----------------------------------------------------------------------------
1701 XclImpXFRangeBuffer::XclImpXFRangeBuffer( const XclImpRoot
& rRoot
) :
1706 XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1710 void XclImpXFRangeBuffer::Initialize()
1713 maHyperlinks
.clear();
1714 maMergeList
.RemoveAll();
1717 void XclImpXFRangeBuffer::SetXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
, XclImpXFInsertMode eMode
)
1719 SCCOL nScCol
= rScPos
.Col();
1720 SCROW nScRow
= rScPos
.Row();
1723 size_t nIndex
= static_cast< size_t >( nScCol
);
1724 if( maColumns
.size() <= nIndex
)
1725 maColumns
.resize( nIndex
+ 1 );
1726 if( !maColumns
[ nIndex
] )
1727 maColumns
[ nIndex
].reset( new XclImpXFRangeColumn
);
1728 // #108770# remember all Boolean cells, they will get 'Standard' number format
1729 maColumns
[ nIndex
]->SetXF( nScRow
, XclImpXFIndex( nXFIndex
, eMode
== xlXFModeBoolCell
) );
1731 // set "center across selection" and "fill" attribute for all following empty cells
1732 // #97130# ignore it on row default XFs
1733 if( eMode
!= xlXFModeRow
)
1735 const XclImpXF
* pXF
= GetXFBuffer().GetXF( nXFIndex
);
1736 if( pXF
&& ((pXF
->GetHorAlign() == EXC_XF_HOR_CENTER_AS
) || (pXF
->GetHorAlign() == EXC_XF_HOR_FILL
)) )
1738 // expand last merged range if this attribute is set repeatedly
1739 ScRange
* pRange
= maMergeList
.Last();
1740 if( pRange
&& (pRange
->aEnd
.Row() == nScRow
) && (pRange
->aEnd
.Col() + 1 == nScCol
)
1741 && (eMode
== xlXFModeBlank
) )
1742 pRange
->aEnd
.IncCol();
1743 else if( eMode
!= xlXFModeBlank
) // #108781# do not merge empty cells
1744 SetMerge( nScCol
, nScRow
);
1749 void XclImpXFRangeBuffer::SetXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1751 SetXF( rScPos
, nXFIndex
, xlXFModeCell
);
1754 void XclImpXFRangeBuffer::SetBlankXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1756 SetXF( rScPos
, nXFIndex
, xlXFModeBlank
);
1759 void XclImpXFRangeBuffer::SetBoolXF( const ScAddress
& rScPos
, sal_uInt16 nXFIndex
)
1761 SetXF( rScPos
, nXFIndex
, xlXFModeBoolCell
);
1764 void XclImpXFRangeBuffer::SetRowDefXF( SCROW nScRow
, sal_uInt16 nXFIndex
)
1766 for( SCCOL nScCol
= 0; nScCol
<= MAXCOL
; ++nScCol
)
1767 SetXF( ScAddress( nScCol
, nScRow
, 0 ), nXFIndex
, xlXFModeRow
);
1770 void XclImpXFRangeBuffer::SetColumnDefXF( SCCOL nScCol
, sal_uInt16 nXFIndex
)
1772 // our array should not have values when creating the default column format.
1773 size_t nIndex
= static_cast< size_t >( nScCol
);
1774 if( maColumns
.size() <= nIndex
)
1775 maColumns
.resize( nIndex
+ 1 );
1776 DBG_ASSERT( !maColumns
[ nIndex
], "XclImpXFRangeBuffer::SetColumnDefXF - default column of XFs already has values" );
1777 maColumns
[ nIndex
].reset( new XclImpXFRangeColumn
);
1778 maColumns
[ nIndex
]->SetDefaultXF( XclImpXFIndex( nXFIndex
) );
1781 void XclImpXFRangeBuffer::SetBorderLine( const ScRange
& rRange
, SCTAB nScTab
, USHORT nLine
)
1783 SCCOL nFromScCol
= (nLine
== BOX_LINE_RIGHT
) ? rRange
.aEnd
.Col() : rRange
.aStart
.Col();
1784 SCROW nFromScRow
= (nLine
== BOX_LINE_BOTTOM
) ? rRange
.aEnd
.Row() : rRange
.aStart
.Row();
1785 ScDocument
& rDoc
= GetDoc();
1787 const SvxBoxItem
* pFromItem
= static_cast< const SvxBoxItem
* >(
1788 rDoc
.GetAttr( nFromScCol
, nFromScRow
, nScTab
, ATTR_BORDER
) );
1789 const SvxBoxItem
* pToItem
= static_cast< const SvxBoxItem
* >(
1790 rDoc
.GetAttr( rRange
.aStart
.Col(), rRange
.aStart
.Row(), nScTab
, ATTR_BORDER
) );
1792 SvxBoxItem
aNewItem( *pToItem
);
1793 aNewItem
.SetLine( pFromItem
->GetLine( nLine
), nLine
);
1794 rDoc
.ApplyAttr( rRange
.aStart
.Col(), rRange
.aStart
.Row(), nScTab
, aNewItem
);
1797 void XclImpXFRangeBuffer::SetHyperlink( const XclRange
& rXclRange
, const String
& rUrl
)
1799 maHyperlinks
.push_back( XclImpHyperlinkRange( rXclRange
, rUrl
) );
1802 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol
, SCROW nScRow
)
1804 maMergeList
.Append( ScRange( nScCol
, nScRow
, 0 ) );
1807 void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol1
, SCROW nScRow1
, SCCOL nScCol2
, SCROW nScRow2
)
1809 if( (nScCol1
< nScCol2
) || (nScRow1
< nScRow2
) )
1810 maMergeList
.Append( ScRange( nScCol1
, nScRow1
, 0, nScCol2
, nScRow2
, 0 ) );
1813 void XclImpXFRangeBuffer::Finalize()
1815 ScDocument
& rDoc
= GetDoc();
1816 SCTAB nScTab
= GetCurrScTab();
1819 XclImpXFBuffer
& rXFBuffer
= GetXFBuffer();
1820 for( XclImpXFRangeColumnVec::const_iterator aVBeg
= maColumns
.begin(), aVEnd
= maColumns
.end(), aVIt
= aVBeg
; aVIt
!= aVEnd
; ++aVIt
)
1822 // apply all cell styles of an existing column
1825 XclImpXFRangeColumn
& rColumn
= **aVIt
;
1826 SCCOL nScCol
= static_cast< SCCOL
>( aVIt
- aVBeg
);
1827 for( XclImpXFRange
* pStyle
= rColumn
.First(); pStyle
; pStyle
= rColumn
.Next() )
1828 rXFBuffer
.ApplyPattern( nScCol
, pStyle
->mnScRow1
, nScCol
, pStyle
->mnScRow2
, nScTab
, pStyle
->maXFIndex
);
1832 // insert hyperlink cells
1833 for( XclImpHyperlinkList::const_iterator aLIt
= maHyperlinks
.begin(), aLEnd
= maHyperlinks
.end(); aLIt
!= aLEnd
; ++aLIt
)
1834 XclImpHyperlink::InsertUrl( GetRoot(), aLIt
->first
, aLIt
->second
);
1836 // apply cell merging
1837 for( const ScRange
* pRange
= maMergeList
.First(); pRange
; pRange
= maMergeList
.Next() )
1839 const ScAddress
& rStart
= pRange
->aStart
;
1840 const ScAddress
& rEnd
= pRange
->aEnd
;
1841 bool bMultiCol
= rStart
.Col() != rEnd
.Col();
1842 bool bMultiRow
= rStart
.Row() != rEnd
.Row();
1843 // set correct right border
1845 SetBorderLine( *pRange
, nScTab
, BOX_LINE_RIGHT
);
1846 // set correct lower border
1848 SetBorderLine( *pRange
, nScTab
, BOX_LINE_BOTTOM
);
1850 if( bMultiCol
|| bMultiRow
)
1851 rDoc
.DoMerge( nScTab
, rStart
.Col(), rStart
.Row(), rEnd
.Col(), rEnd
.Row() );
1852 // #i93609# merged range in a single row: test if manual row height is needed
1855 bool bTextWrap
= static_cast< const SfxBoolItem
* >( rDoc
.GetAttr( rStart
.Col(), rStart
.Row(), rStart
.Tab(), ATTR_LINEBREAK
) )->GetValue();
1856 if( !bTextWrap
&& (rDoc
.GetCellType( rStart
) == CELLTYPE_EDIT
) )
1857 if( const EditTextObject
* pEditObj
= static_cast< const ScEditCell
* >( rDoc
.GetCell( rStart
) )->GetData() )
1858 bTextWrap
= pEditObj
->GetParagraphCount() > 1;
1860 GetOldRoot().pColRowBuff
->SetManualRowHeight( rStart
.Row() );
1865 // ============================================================================