update dev300-m58
[ooovba.git] / sc / source / filter / excel / xistyle.cxx
blobd81bcc5316602639ffdf4185aee7ccb75f7d3590
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"
59 #include "attrib.hxx"
60 #include "stlpool.hxx"
61 #include "stlsheet.hxx"
62 #include "cell.hxx"
63 #include "globstr.hrc"
64 #include "xltracer.hxx"
65 #include "xistream.hxx"
66 #include "xicontent.hxx"
68 #include "root.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
81 public:
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);
106 private:
107 ColorDataVec maColorData;
110 void
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 );
123 if ( xProps.is() )
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 )
156 sal_uInt16 nCount;
157 rStrm >> nCount;
158 DBG_ASSERT( rStrm.GetRecLeft() == static_cast< sal_Size >( 4 * nCount ),
159 "XclImpPalette::ReadPalette - size mismatch" );
161 maColorTable.resize( nCount );
162 Color aColor;
163 for( sal_uInt16 nIndex = 0; nIndex < nCount; ++nIndex )
165 rStrm >> aColor;
166 maColorTable[ nIndex ] = aColor.GetColor();
168 ExportPalette();
171 // FONT record - font information =============================================
173 XclImpFont::XclImpFont( const XclImpRoot& rRoot ) :
174 XclImpRoot( rRoot ),
175 mbHasCharSet( false ),
176 mbHasWstrn( true ),
177 mbHasAsian( false ),
178 mbHasCmplx( false )
180 SetAllUsedFlags( false );
183 XclImpFont::XclImpFont( const XclImpRoot& rRoot, const XclFontData& rFontData ) :
184 XclImpRoot( rRoot )
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 )
197 maData = rFontData;
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();
216 GuessScriptType();
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 )
230 switch( GetBiff() )
232 case EXC_BIFF2:
233 ReadFontData2( rStrm );
234 ReadFontName2( rStrm );
235 break;
236 case EXC_BIFF3:
237 case EXC_BIFF4:
238 ReadFontData2( rStrm );
239 ReadFontColor( rStrm );
240 ReadFontName2( rStrm );
241 break;
242 case EXC_BIFF5:
243 ReadFontData5( rStrm );
244 ReadFontName2( rStrm );
245 break;
246 case EXC_BIFF8:
247 ReadFontData5( rStrm );
248 ReadFontName8( rStrm );
249 break;
250 default:
251 DBG_ERROR_BIFF();
252 return;
254 GuessScriptType();
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 )
267 return;
269 sal_uInt32 nHeight, nStyle, nColor, nFontFlags1, nFontFlags2, nFontFlags3;
270 sal_uInt16 nWeight, nEscapem;
271 sal_uInt8 nUnderl;
273 rStrm.Ignore( 64 );
274 rStrm >> nHeight >> nStyle >> nWeight >> nEscapem >> nUnderl;
275 rStrm.Ignore( 3 );
276 rStrm >> nColor;
277 rStrm.Ignore( 4 );
278 rStrm >> nFontFlags1 >> nFontFlags2 >> nFontFlags3;
279 rStrm.Ignore( 18 );
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 )
306 // Font item
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
318 if( mbHasWstrn )
319 PUTITEM( aFontItem, ATTR_FONT, EE_CHAR_FONTINFO );
320 if( mbHasAsian )
321 PUTITEM( aFontItem, ATTR_CJK_FONT, EE_CHAR_FONTINFO_CJK );
322 if( mbHasCmplx )
323 PUTITEM( aFontItem, ATTR_CTL_FONT, EE_CHAR_FONTINFO_CTL );
326 // Font height (for all script types)
327 if( mbHeightUsed )
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
340 if( mbColorUsed )
341 PUTITEM( SvxColorItem( maData.maColor, ATTR_FONT_COLOR ), ATTR_FONT_COLOR, EE_CHAR_COLOR );
343 // Font weight (for all script types)
344 if( mbWeightUsed )
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 );
352 // Font underline
353 if( mbUnderlUsed )
355 SvxUnderlineItem aUnderlItem( maData.GetScUnderline(), ATTR_FONT_UNDERLINE );
356 PUTITEM( aUnderlItem, ATTR_FONT_UNDERLINE, EE_CHAR_UNDERLINE );
359 // Font posture (for all script types)
360 if( mbItalicUsed )
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
369 if( mbStrikeUsed )
370 PUTITEM( SvxCrossedOutItem( maData.GetScStrikeout(), ATTR_FONT_CROSSEDOUT ), ATTR_FONT_CROSSEDOUT, EE_CHAR_STRIKEOUT );
371 if( mbOutlineUsed )
372 PUTITEM( SvxContourItem( maData.mbOutline, ATTR_FONT_CONTOUR ), ATTR_FONT_CONTOUR, EE_CHAR_OUTLINE );
373 if( mbShadowUsed )
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 ) );
380 #undef PUTITEM
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 )
392 sal_uInt16 nFlags;
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 )
406 sal_uInt16 nFlags;
408 rStrm >> maData.mnHeight >> nFlags;
409 ReadFontColor( rStrm );
410 rStrm >> maData.mnWeight >> maData.mnEscapem >> maData.mnUnderline >> maData.mnFamily >> maData.mnCharSet;
411 rStrm.Ignore( 1 );
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 );
417 mbHasCharSet = true;
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()
437 mbHasWstrn = true;
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 ) )
449 // #91658# CJK fonts
450 mbHasAsian =
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
465 mbHasCmplx =
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
474 // Western fonts
475 mbHasWstrn = (!mbHasAsian && !mbHasCmplx) || aCharMap.HasChar( 'A' );
480 // ----------------------------------------------------------------------------
482 XclImpFontBuffer::XclImpFontBuffer( const XclImpRoot& rRoot ) :
483 XclImpRoot( rRoot ),
484 maFont4( rRoot ),
485 maCtrlFont( rRoot )
487 Initialize();
489 // default font for form controls without own font information
490 XclFontData aCtrlFontData;
491 switch( GetBiff() )
493 case EXC_BIFF2:
494 case EXC_BIFF3:
495 case EXC_BIFF4:
496 case EXC_BIFF5:
497 aCtrlFontData.maName.AssignAscii( "Helv" );
498 aCtrlFontData.mnHeight = 160;
499 aCtrlFontData.mnWeight = EXC_FONTWGHT_BOLD;
500 break;
501 case EXC_BIFF8:
502 aCtrlFontData.maName.AssignAscii( "Tahoma" );
503 aCtrlFontData.mnHeight = 160;
504 aCtrlFontData.mnWeight = EXC_FONTWGHT_NORMAL;
505 break;
506 default:
507 DBG_ERROR_BIFF();
509 maCtrlFont.SetFontData( aCtrlFontData, false );
512 void XclImpFontBuffer::Initialize()
514 maFontList.Clear();
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 ),
588 XclImpRoot( rRoot ),
589 mnNextXclIdx( 0 )
593 void XclImpNumFmtBuffer::Initialize()
595 maIndexMap.clear();
596 mnNextXclIdx = 0;
597 InitializeImport(); // base class
600 void XclImpNumFmtBuffer::ReadFormat( XclImpStream& rStrm )
602 String aFormat;
603 switch( GetBiff() )
605 case EXC_BIFF2:
606 case EXC_BIFF3:
607 aFormat = rStrm.ReadByteString( false );
608 break;
610 case EXC_BIFF4:
611 rStrm.Ignore( 2 ); // in BIFF4 the index field exists, but is undefined
612 aFormat = rStrm.ReadByteString( false );
613 break;
615 case EXC_BIFF5:
616 rStrm >> mnNextXclIdx;
617 aFormat = rStrm.ReadByteString( false );
618 break;
620 case EXC_BIFF8:
621 rStrm >> mnNextXclIdx;
622 aFormat = rStrm.ReadUniString();
623 break;
625 default:
626 DBG_ERROR_BIFF();
627 return;
630 if( mnNextXclIdx < 0xFFFF )
632 InsertFormat( mnNextXclIdx, aFormat );
633 ++mnNextXclIdx;
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;
649 sal_uInt32 nKey;
650 if( rNumFmt.maFormat.Len() )
652 String aFormat( rNumFmt.maFormat );
653 rFormatter.PutandConvertEntry( aFormat, nCheckPos,
654 nType, nKey, LANGUAGE_ENGLISH_US, rNumFmt.meLanguage );
656 else
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 );
757 // indent
758 sal_uInt16 nScIndent = mnIndent * 200; // 1 Excel unit == 10 pt == 200 twips
759 ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_INDENT, nScIndent ), bSkipPoolDefs );
761 // shrink to fit
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 );
863 mbDiagUsed = false;
866 namespace {
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 )
891 return false;
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 ] );
899 return true;
902 } // namespace
904 void XclImpCellBorder::FillToItemSet( SfxItemSet& rItemSet, const XclImpPalette& rPalette, bool bSkipPoolDefs ) const
906 if( mbLeftUsed || mbRightUsed || mbTopUsed || mbBottomUsed )
908 SvxBoxItem aBoxItem( ATTR_BORDER );
909 SvxBorderLine aLine;
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 );
920 if( mbDiagUsed )
922 SvxLineItem aTLBRItem( ATTR_BORDER_TLBR );
923 SvxLineItem aBLTRItem( ATTR_BORDER_BLTR );
924 SvxBorderLine aLine;
925 if( lclConvertBorderLine( aLine, rPalette, mnDiagLine, mnDiagColor ) )
927 if( mbDiagTLtoBR )
928 aTLBRItem.SetLine( &aLine );
929 if( mbDiagBLtoTR )
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) )
998 mbPattUsed = false;
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 ) );
1013 else
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 ),
1030 mpStyleSheet( 0 ),
1031 mnXclNumFmt( 0 ),
1032 mnXclFont( 0 ),
1033 mbWasBuiltIn( false ),
1034 mbForceCreate( false )
1038 XclImpXF::~XclImpXF()
1042 void XclImpXF::ReadXF2( XclImpStream& rStrm )
1044 sal_uInt8 nReadFont, nReadNumFmt, nFlags;
1045 rStrm >> nReadFont;
1046 rStrm.Ignore( 1 );
1047 rStrm >> nReadNumFmt >> nFlags;
1049 // XF type always cell, no parent, used flags always true
1050 SetAllUsedFlags( true );
1052 // attributes
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 )
1063 sal_uInt32 nBorder;
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 ) );
1073 // attributes
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 )
1084 sal_uInt32 nBorder;
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 ) );
1094 // attributes
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 ) );
1114 // attributes
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 ) );
1132 // attributes
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 )
1141 switch( GetBiff() )
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 )
1177 CreateStyleSheet();
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. */
1226 if( !mbProtUsed )
1227 mbProtUsed = !rParentXF.mbProtUsed || !(maProtection == rParentXF.maProtection);
1228 if( !mbFontUsed )
1229 mbFontUsed = !rParentXF.mbFontUsed || (mnXclFont != rParentXF.mnXclFont);
1230 if( !mbFmtUsed )
1231 mbFmtUsed = !rParentXF.mbFmtUsed || (mnXclNumFmt != rParentXF.mnXclNumFmt);
1232 if( !mbAlignUsed )
1233 mbAlignUsed = !rParentXF.mbAlignUsed || !(maAlignment == rParentXF.maAlignment);
1234 if( !mbBorderUsed )
1235 mbBorderUsed = !rParentXF.mbBorderUsed || !(maBorder == rParentXF.maBorder);
1236 if( !mbAreaUsed )
1237 mbAreaUsed = !rParentXF.mbAreaUsed || !(maArea == rParentXF.maArea);
1240 const ScPatternAttr& XclImpXF::CreatePattern( bool bSkipPoolDefs )
1242 if( mpPattern.get() )
1243 return *mpPattern;
1245 // create new pattern attribute set
1246 mpPattern.reset( new ScPatternAttr( GetDoc().GetPool() ) );
1247 SfxItemSet& rItemSet = mpPattern->GetItemSet();
1249 // parent cell style
1250 if( IsCellXF() )
1252 if( XclImpXF* pParentXF = GetXFBuffer().GetXF( mnParent ) )
1254 mpStyleSheet = pParentXF->CreateStyleSheet();
1255 UpdateUsedFlags( *pParentXF );
1259 // cell protection
1260 if( mbProtUsed )
1261 maProtection.FillToItemSet( rItemSet, bSkipPoolDefs );
1263 // font
1264 if( mbFontUsed )
1265 GetFontBuffer().FillToItemSet( rItemSet, EXC_FONTITEM_CELL, mnXclFont, bSkipPoolDefs );
1267 // value format
1268 if( mbFmtUsed )
1270 GetNumFmtBuffer().FillToItemSet( rItemSet, mnXclNumFmt, bSkipPoolDefs );
1271 // Trace occurrences of Windows date formats
1272 GetTracer().TraceDates( mnXclNumFmt );
1275 // alignment
1276 if( mbAlignUsed )
1277 maAlignment.FillToItemSet( rItemSet, GetFontBuffer().GetFont( mnXclFont ), bSkipPoolDefs );
1279 // border
1280 if( mbBorderUsed )
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 );
1288 // area
1289 if( mbAreaUsed )
1291 maArea.FillToItemSet( rItemSet, GetPalette(), bSkipPoolDefs );
1292 GetTracer().TraceFillPattern(maArea.mnPattern != EXC_PATT_NONE &&
1293 maArea.mnPattern != EXC_PATT_SOLID);
1296 return *mpPattern;
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 ));
1305 if( bDefStyle )
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" );
1314 else
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()
1322 if( mpStyleSheet )
1323 mpStyleSheet->GetItemSet().Put( CreatePattern( bDefStyle ).GetItemSet() );
1325 return mpStyleSheet;
1328 // ----------------------------------------------------------------------------
1330 XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot& rRoot ) :
1331 XclImpRoot( rRoot )
1335 void XclImpXFBuffer::Initialize()
1337 maXFList.Clear();
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;
1356 rStrm >> 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
1369 String aStyleName;
1370 if( GetBiff() <= EXC_BIFF5 )
1371 aStyleName = rStrm.ReadByteString( false ); // 8 bit length
1372 else
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 )
1416 return false;
1418 if( mnScRow2 + 1 == nScRow )
1420 ++mnScRow2;
1421 return true;
1423 if( mnScRow1 > 0 && (mnScRow1 - 1 == nScRow) )
1425 --mnScRow1;
1426 return true;
1429 return false;
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;
1438 return true;
1440 return false;
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;
1461 ULONG nNextIndex;
1463 Find( pPrevRange, pNextRange, nNextIndex, nScRow );
1465 // previous range:
1466 // try to overwrite XF (if row is contained in) or try to expand range
1467 if( pPrevRange )
1469 if( pPrevRange->Contains( nScRow ) ) // overwrite old XF
1471 if( rXFIndex == pPrevRange->maXFIndex )
1472 return;
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 );
1506 return;
1508 else if( pPrevRange->Expand( nScRow, rXFIndex ) ) // try to expand
1510 TryConcatPrev( nNextIndex ); // try to concatenate next with expanded
1511 return;
1515 // try to expand next range
1516 if( pNextRange && pNextRange->Expand( nScRow, rXFIndex ) )
1517 return;
1519 // create new range
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;
1532 rnNextIndex = 0;
1533 return;
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;
1544 rpNextRange = 0;
1545 rnNextIndex = maIndexList.Count();
1546 return;
1549 // test whether row is at beginning of list (really before first range)
1550 if( nScRow < rpPrevRange->mnScRow1 )
1552 rpNextRange = rpPrevRange;
1553 rpPrevRange = 0;
1554 rnNextIndex = 0;
1555 return;
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;
1562 ULONG nMidIndex;
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 )
1592 if( !nIndex )
1593 return;
1595 XclImpXFRange* pPrevRange = maIndexList.GetObject( nIndex - 1 );
1596 XclImpXFRange* pNextRange = maIndexList.GetObject( nIndex );
1597 if( !pPrevRange || !pNextRange )
1598 return;
1600 if( pPrevRange->Expand( *pNextRange ) )
1601 maIndexList.Delete( nIndex );
1604 // ----------------------------------------------------------------------------
1606 XclImpXFRangeBuffer::XclImpXFRangeBuffer( const XclImpRoot& rRoot ) :
1607 XclImpRoot( rRoot )
1611 XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1615 void XclImpXFRangeBuffer::Initialize()
1617 maColumns.clear();
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();
1627 // set cell XF's
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();
1723 // apply patterns
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
1728 if( aVIt->is() )
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
1749 if( bMultiCol )
1750 SetBorderLine( *pRange, nScTab, BOX_LINE_RIGHT );
1751 // set correct lower border
1752 if( bMultiRow )
1753 SetBorderLine( *pRange, nScTab, BOX_LINE_BOTTOM );
1754 // do merge
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
1758 if( !bMultiRow )
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;
1764 if( bTextWrap )
1765 GetOldRoot().pColRowBuff->SetManualRowHeight( rStart.Row() );
1770 // ============================================================================