Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xistyle.hxx"
21 : #include <sfx2/printer.hxx>
22 : #include <sfx2/objsh.hxx>
23 : #include <svtools/ctrltool.hxx>
24 : #include <editeng/editobj.hxx>
25 : #include "scitems.hxx"
26 : #include <editeng/fontitem.hxx>
27 : #include <editeng/fhgtitem.hxx>
28 : #include <editeng/wghtitem.hxx>
29 : #include <editeng/udlnitem.hxx>
30 : #include <editeng/postitem.hxx>
31 : #include <editeng/crossedoutitem.hxx>
32 : #include <editeng/contouritem.hxx>
33 : #include <editeng/shdditem.hxx>
34 : #include <editeng/escapementitem.hxx>
35 : #include <svx/algitem.hxx>
36 : #include <editeng/boxitem.hxx>
37 : #include <editeng/lineitem.hxx>
38 : #include <svx/rotmodit.hxx>
39 : #include <editeng/colritem.hxx>
40 : #include <editeng/brushitem.hxx>
41 : #include <editeng/frmdiritem.hxx>
42 : #include <editeng/eeitem.hxx>
43 : #include <editeng/flstitem.hxx>
44 : #include <editeng/justifyitem.hxx>
45 : #include <sal/macros.h>
46 : #include "document.hxx"
47 : #include "docpool.hxx"
48 : #include "attrib.hxx"
49 : #include "stlpool.hxx"
50 : #include "stlsheet.hxx"
51 : #include "formulacell.hxx"
52 : #include "globstr.hrc"
53 : #include "attarray.hxx"
54 : #include "xltracer.hxx"
55 : #include "xistream.hxx"
56 : #include "xicontent.hxx"
57 :
58 : #include "root.hxx"
59 : #include "colrowst.hxx"
60 : #include <svl/poolcach.hxx>
61 :
62 : #include <list>
63 :
64 : using ::std::list;
65 :
66 : #include <cppuhelper/implbase1.hxx>
67 : #include <com/sun/star/container/XIndexAccess.hpp>
68 : #include <com/sun/star/beans/XPropertySet.hpp>
69 : using namespace ::com::sun::star;
70 :
71 : typedef ::cppu::WeakImplHelper1< container::XIndexAccess > XIndexAccess_BASE;
72 : typedef ::std::vector< ColorData > ColorDataVec;
73 :
74 24 : class PaletteIndex : public XIndexAccess_BASE
75 : {
76 : public:
77 12 : PaletteIndex( const ColorDataVec& rColorDataTable ) : maColorData( rColorDataTable ) {}
78 :
79 : // Methods XIndexAccess
80 0 : virtual ::sal_Int32 SAL_CALL getCount() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
81 : {
82 0 : return maColorData.size();
83 : }
84 :
85 0 : virtual uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, uno::RuntimeException, std::exception) SAL_OVERRIDE
86 : {
87 : //--Index; // apparently the palette is already 1 based
88 0 : return uno::makeAny( sal_Int32( maColorData[ Index ] ) );
89 : }
90 :
91 : // Methods XElementAcess
92 0 : virtual uno::Type SAL_CALL getElementType() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
93 : {
94 0 : return ::cppu::UnoType<sal_Int32>::get();
95 : }
96 0 : virtual sal_Bool SAL_CALL hasElements() throw (uno::RuntimeException, std::exception) SAL_OVERRIDE
97 : {
98 0 : return (maColorData.size() > 0);
99 : }
100 :
101 : private:
102 : ColorDataVec maColorData;
103 : };
104 :
105 : void
106 12 : XclImpPalette::ExportPalette()
107 : {
108 12 : if( SfxObjectShell* pDocShell = mrRoot.GetDocShell() )
109 : {
110 : // copy values in color palette
111 12 : sal_Int16 nColors = maColorTable.size();
112 12 : ColorDataVec aColors;
113 12 : aColors.resize( nColors );
114 1594 : for( sal_uInt16 nIndex = 0; nIndex < nColors; ++nIndex )
115 1582 : aColors[ nIndex ] = GetColorData( nIndex );
116 :
117 24 : uno::Reference< beans::XPropertySet > xProps( pDocShell->GetModel(), uno::UNO_QUERY );
118 12 : if ( xProps.is() )
119 : {
120 12 : uno::Reference< container::XIndexAccess > xIndex( new PaletteIndex( aColors ) );
121 12 : xProps->setPropertyValue( "ColorPalette", uno::makeAny( xIndex ) );
122 12 : }
123 : }
124 :
125 12 : }
126 : // PALETTE record - color information =========================================
127 :
128 144 : XclImpPalette::XclImpPalette( const XclImpRoot& rRoot ) :
129 144 : XclDefaultPalette( rRoot ), mrRoot( rRoot )
130 : {
131 144 : }
132 :
133 0 : void XclImpPalette::Initialize()
134 : {
135 0 : maColorTable.clear();
136 0 : }
137 :
138 18896 : ColorData XclImpPalette::GetColorData( sal_uInt16 nXclIndex ) const
139 : {
140 18896 : if( nXclIndex >= EXC_COLOR_USEROFFSET )
141 : {
142 18800 : sal_uInt32 nIx = nXclIndex - EXC_COLOR_USEROFFSET;
143 18800 : if( nIx < maColorTable.size() )
144 1884 : return maColorTable[ nIx ];
145 : }
146 17012 : return GetDefColorData( nXclIndex );
147 : }
148 :
149 12 : void XclImpPalette::ReadPalette( XclImpStream& rStrm )
150 : {
151 : sal_uInt16 nCount;
152 12 : rStrm >> nCount;
153 : OSL_ENSURE( rStrm.GetRecLeft() == static_cast< sal_Size >( 4 * nCount ),
154 : "XclImpPalette::ReadPalette - size mismatch" );
155 :
156 12 : maColorTable.resize( nCount );
157 12 : Color aColor;
158 1594 : for( sal_uInt16 nIndex = 0; nIndex < nCount; ++nIndex )
159 : {
160 1582 : rStrm >> aColor;
161 1582 : maColorTable[ nIndex ] = aColor.GetColor();
162 : }
163 12 : ExportPalette();
164 12 : }
165 :
166 : // FONT record - font information =============================================
167 :
168 1846 : XclImpFont::XclImpFont( const XclImpRoot& rRoot ) :
169 : XclImpRoot( rRoot ),
170 : mbHasCharSet( false ),
171 : mbHasWstrn( true ),
172 : mbHasAsian( false ),
173 1846 : mbHasCmplx( false )
174 : {
175 1846 : SetAllUsedFlags( false );
176 1846 : }
177 :
178 116 : XclImpFont::XclImpFont( const XclImpRoot& rRoot, const XclFontData& rFontData ) :
179 116 : XclImpRoot( rRoot )
180 : {
181 116 : SetFontData( rFontData, false );
182 116 : }
183 :
184 3948 : void XclImpFont::SetAllUsedFlags( bool bUsed )
185 : {
186 : mbFontNameUsed = mbHeightUsed = mbColorUsed = mbWeightUsed = mbEscapemUsed =
187 3948 : mbUnderlUsed = mbItalicUsed = mbStrikeUsed = mbOutlineUsed = mbShadowUsed = bUsed;
188 3948 : }
189 :
190 544 : void XclImpFont::SetFontData( const XclFontData& rFontData, bool bHasCharSet )
191 : {
192 544 : maData = rFontData;
193 544 : mbHasCharSet = bHasCharSet;
194 544 : if( !maData.maStyle.isEmpty() )
195 : {
196 16 : if( SfxObjectShell* pDocShell = GetDocShell() )
197 : {
198 16 : if( const SvxFontListItem* pInfoItem = static_cast< const SvxFontListItem* >(
199 16 : pDocShell->GetItem( SID_ATTR_CHAR_FONTLIST ) ) )
200 : {
201 16 : if( const FontList* pFontList = pInfoItem->GetFontList() )
202 : {
203 16 : vcl::FontInfo aFontInfo( pFontList->Get( maData.maName, maData.maStyle ) );
204 16 : maData.SetScWeight( aFontInfo.GetWeight() );
205 16 : maData.SetScPosture( aFontInfo.GetItalic() );
206 : }
207 : }
208 : }
209 16 : maData.maStyle = "";
210 : }
211 544 : GuessScriptType();
212 544 : SetAllUsedFlags( true );
213 544 : }
214 :
215 1640 : rtl_TextEncoding XclImpFont::GetFontEncoding() const
216 : {
217 : // #i63105# use text encoding from FONT record
218 : // #i67768# BIFF2-BIFF4 FONT records do not contain character set
219 1640 : rtl_TextEncoding eFontEnc = mbHasCharSet ? maData.GetFontEncoding() : GetTextEncoding();
220 1640 : return (eFontEnc == RTL_TEXTENCODING_DONTKNOW) ? GetTextEncoding() : eFontEnc;
221 : }
222 :
223 1558 : void XclImpFont::ReadFont( XclImpStream& rStrm )
224 : {
225 1558 : switch( GetBiff() )
226 : {
227 : case EXC_BIFF2:
228 0 : ReadFontData2( rStrm );
229 0 : ReadFontName2( rStrm );
230 0 : break;
231 : case EXC_BIFF3:
232 : case EXC_BIFF4:
233 0 : ReadFontData2( rStrm );
234 0 : ReadFontColor( rStrm );
235 0 : ReadFontName2( rStrm );
236 0 : break;
237 : case EXC_BIFF5:
238 46 : ReadFontData5( rStrm );
239 46 : ReadFontName2( rStrm );
240 46 : break;
241 : case EXC_BIFF8:
242 1512 : ReadFontData5( rStrm );
243 1512 : ReadFontName8( rStrm );
244 1512 : break;
245 : default:
246 : DBG_ERROR_BIFF();
247 1558 : return;
248 : }
249 1558 : GuessScriptType();
250 1558 : SetAllUsedFlags( true );
251 : }
252 :
253 0 : void XclImpFont::ReadEfont( XclImpStream& rStrm )
254 : {
255 0 : ReadFontColor( rStrm );
256 0 : }
257 :
258 0 : void XclImpFont::ReadCFFontBlock( XclImpStream& rStrm )
259 : {
260 : OSL_ENSURE_BIFF( GetBiff() == EXC_BIFF8 );
261 0 : if( GetBiff() != EXC_BIFF8 )
262 0 : return;
263 :
264 : sal_uInt32 nHeight, nStyle, nColor, nFontFlags1, nFontFlags2, nFontFlags3;
265 : sal_uInt16 nWeight, nEscapem;
266 : sal_uInt8 nUnderl;
267 :
268 0 : rStrm.Ignore( 64 );
269 0 : rStrm >> nHeight >> nStyle >> nWeight >> nEscapem >> nUnderl;
270 0 : rStrm.Ignore( 3 );
271 0 : rStrm >> nColor;
272 0 : rStrm.Ignore( 4 );
273 0 : rStrm >> nFontFlags1 >> nFontFlags2 >> nFontFlags3;
274 0 : rStrm.Ignore( 18 );
275 :
276 0 : if( (mbHeightUsed = (nHeight <= 0x7FFF)) == true )
277 0 : maData.mnHeight = static_cast< sal_uInt16 >( nHeight );
278 0 : if( (mbWeightUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STYLE ) && (nWeight < 0x7FFF)) == true )
279 0 : maData.mnWeight = static_cast< sal_uInt16 >( nWeight );
280 0 : if( (mbItalicUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STYLE )) == true )
281 0 : maData.mbItalic = ::get_flag( nStyle, EXC_CF_FONT_STYLE );
282 0 : if( (mbUnderlUsed = !::get_flag( nFontFlags3, EXC_CF_FONT_UNDERL ) && (nUnderl <= 0x7F)) == true )
283 0 : maData.mnUnderline = nUnderl;
284 0 : if( (mbColorUsed = (nColor <= 0x7FFF)) == true )
285 0 : maData.maColor = GetPalette().GetColor( static_cast< sal_uInt16 >( nColor ) );
286 0 : if( (mbStrikeUsed = !::get_flag( nFontFlags1, EXC_CF_FONT_STRIKEOUT )) == true )
287 0 : maData.mbStrikeout = ::get_flag( nStyle, EXC_CF_FONT_STRIKEOUT );
288 : }
289 :
290 2882 : void XclImpFont::FillToItemSet( SfxItemSet& rItemSet, XclFontItemType eType, bool bSkipPoolDefs ) const
291 : {
292 : // true = edit engine Which-IDs (EE_CHAR_*); false = Calc Which-IDs (ATTR_*)
293 2882 : bool bEE = eType != EXC_FONTITEM_CELL;
294 :
295 : // item = the item to put into the item set
296 : // sc_which = the Calc Which-ID of the item
297 : // ee_which = the edit engine Which-ID of the item
298 : #define PUTITEM( item, sc_which, ee_which ) \
299 : ScfTools::PutItem( rItemSet, item, (bEE ? (ee_which) : (sc_which)), bSkipPoolDefs )
300 :
301 : // Font item
302 : // #i36997# do not set default Tahoma font from notes
303 2882 : bool bDefNoteFont = (eType == EXC_FONTITEM_NOTE) && (maData.maName.equalsIgnoreAsciiCase( "Tahoma" ));
304 2882 : if( mbFontNameUsed && !bDefNoteFont )
305 : {
306 2882 : rtl_TextEncoding eFontEnc = maData.GetFontEncoding();
307 326 : rtl_TextEncoding eTempTextEnc = (bEE && (eFontEnc == GetTextEncoding())) ?
308 3196 : ScfTools::GetSystemTextEncoding() : eFontEnc;
309 :
310 : //add corresponding pitch for FontFamily
311 2882 : FontPitch ePitch = PITCH_DONTKNOW;
312 2882 : FontFamily eFtFamily = maData.GetScFamily( GetTextEncoding() );
313 2882 : switch( eFtFamily ) //refer http://msdn.microsoft.com/en-us/library/aa246306(v=VS.60).aspx
314 : {
315 2 : case FAMILY_ROMAN: ePitch = PITCH_VARIABLE; break;
316 2054 : case FAMILY_SWISS: ePitch = PITCH_VARIABLE; break;
317 186 : case FAMILY_MODERN: ePitch = PITCH_FIXED; break;
318 640 : default: break;
319 : }
320 2882 : SvxFontItem aFontItem( eFtFamily , maData.maName, EMPTY_OUSTRING, ePitch, eTempTextEnc, ATTR_FONT );
321 :
322 : // set only for valid script types
323 2882 : if( mbHasWstrn )
324 2882 : PUTITEM( aFontItem, ATTR_FONT, EE_CHAR_FONTINFO );
325 2882 : if( mbHasAsian )
326 0 : PUTITEM( aFontItem, ATTR_CJK_FONT, EE_CHAR_FONTINFO_CJK );
327 2882 : if( mbHasCmplx )
328 1384 : PUTITEM( aFontItem, ATTR_CTL_FONT, EE_CHAR_FONTINFO_CTL );
329 : }
330 :
331 : // Font height (for all script types)
332 2882 : if( mbHeightUsed )
333 : {
334 2882 : sal_Int32 nHeight = maData.mnHeight;
335 2882 : if( bEE && (eType != EXC_FONTITEM_HF) ) // do not convert header/footer height
336 210 : nHeight = (nHeight * 127 + 36) / EXC_POINTS_PER_INCH; // 1 in == 72 pt
337 :
338 2882 : SvxFontHeightItem aHeightItem( nHeight, 100, ATTR_FONT_HEIGHT );
339 2882 : PUTITEM( aHeightItem, ATTR_FONT_HEIGHT, EE_CHAR_FONTHEIGHT );
340 2882 : PUTITEM( aHeightItem, ATTR_CJK_FONT_HEIGHT, EE_CHAR_FONTHEIGHT_CJK );
341 2882 : PUTITEM( aHeightItem, ATTR_CTL_FONT_HEIGHT, EE_CHAR_FONTHEIGHT_CTL );
342 : }
343 :
344 : // Font color - pass AUTO_COL to item
345 2882 : if( mbColorUsed )
346 2882 : PUTITEM( SvxColorItem( maData.maColor, ATTR_FONT_COLOR ), ATTR_FONT_COLOR, EE_CHAR_COLOR );
347 :
348 : // Font weight (for all script types)
349 2882 : if( mbWeightUsed )
350 : {
351 2882 : SvxWeightItem aWeightItem( maData.GetScWeight(), ATTR_FONT_WEIGHT );
352 2882 : PUTITEM( aWeightItem, ATTR_FONT_WEIGHT, EE_CHAR_WEIGHT );
353 2882 : PUTITEM( aWeightItem, ATTR_CJK_FONT_WEIGHT, EE_CHAR_WEIGHT_CJK );
354 2882 : PUTITEM( aWeightItem, ATTR_CTL_FONT_WEIGHT, EE_CHAR_WEIGHT_CTL );
355 : }
356 :
357 : // Font underline
358 2882 : if( mbUnderlUsed )
359 : {
360 2882 : SvxUnderlineItem aUnderlItem( maData.GetScUnderline(), ATTR_FONT_UNDERLINE );
361 2882 : PUTITEM( aUnderlItem, ATTR_FONT_UNDERLINE, EE_CHAR_UNDERLINE );
362 : }
363 :
364 : // Font posture (for all script types)
365 2882 : if( mbItalicUsed )
366 : {
367 2882 : SvxPostureItem aPostItem( maData.GetScPosture(), ATTR_FONT_POSTURE );
368 2882 : PUTITEM( aPostItem, ATTR_FONT_POSTURE, EE_CHAR_ITALIC );
369 2882 : PUTITEM( aPostItem, ATTR_CJK_FONT_POSTURE, EE_CHAR_ITALIC_CJK );
370 2882 : PUTITEM( aPostItem, ATTR_CTL_FONT_POSTURE, EE_CHAR_ITALIC_CTL );
371 : }
372 :
373 : // Boolean attributes crossed out, contoured, shadowed
374 2882 : if( mbStrikeUsed )
375 2882 : PUTITEM( SvxCrossedOutItem( maData.GetScStrikeout(), ATTR_FONT_CROSSEDOUT ), ATTR_FONT_CROSSEDOUT, EE_CHAR_STRIKEOUT );
376 2882 : if( mbOutlineUsed )
377 2882 : PUTITEM( SvxContourItem( maData.mbOutline, ATTR_FONT_CONTOUR ), ATTR_FONT_CONTOUR, EE_CHAR_OUTLINE );
378 2882 : if( mbShadowUsed )
379 2882 : PUTITEM( SvxShadowedItem( maData.mbShadow, ATTR_FONT_SHADOWED ), ATTR_FONT_SHADOWED, EE_CHAR_SHADOW );
380 :
381 : // Super-/subscript: only on edit engine objects
382 2882 : if( mbEscapemUsed && bEE )
383 326 : rItemSet.Put( SvxEscapementItem( maData.GetScEscapement(), EE_CHAR_ESCAPEMENT ) );
384 :
385 : #undef PUTITEM
386 2882 : }
387 :
388 398 : void XclImpFont::WriteFontProperties( ScfPropertySet& rPropSet,
389 : XclFontPropSetType eType, const Color* pFontColor ) const
390 : {
391 398 : GetFontPropSetHelper().WriteFontProperties(
392 796 : rPropSet, eType, maData, mbHasWstrn, mbHasAsian, mbHasCmplx, pFontColor );
393 398 : }
394 :
395 0 : void XclImpFont::ReadFontData2( XclImpStream& rStrm )
396 : {
397 : sal_uInt16 nFlags;
398 0 : rStrm >> maData.mnHeight >> nFlags;
399 :
400 0 : maData.mnWeight = ::get_flagvalue( nFlags, EXC_FONTATTR_BOLD, EXC_FONTWGHT_BOLD, EXC_FONTWGHT_NORMAL );
401 0 : maData.mnUnderline = ::get_flagvalue( nFlags, EXC_FONTATTR_UNDERLINE, EXC_FONTUNDERL_SINGLE, EXC_FONTUNDERL_NONE );
402 0 : maData.mbItalic = ::get_flag( nFlags, EXC_FONTATTR_ITALIC );
403 0 : maData.mbStrikeout = ::get_flag( nFlags, EXC_FONTATTR_STRIKEOUT );
404 0 : maData.mbOutline = ::get_flag( nFlags, EXC_FONTATTR_OUTLINE );
405 0 : maData.mbShadow = ::get_flag( nFlags, EXC_FONTATTR_SHADOW );
406 0 : mbHasCharSet = false;
407 0 : }
408 :
409 1558 : void XclImpFont::ReadFontData5( XclImpStream& rStrm )
410 : {
411 : sal_uInt16 nFlags;
412 :
413 1558 : rStrm >> maData.mnHeight >> nFlags;
414 1558 : ReadFontColor( rStrm );
415 1558 : rStrm >> maData.mnWeight >> maData.mnEscapem >> maData.mnUnderline >> maData.mnFamily >> maData.mnCharSet;
416 1558 : rStrm.Ignore( 1 );
417 :
418 1558 : maData.mbItalic = ::get_flag( nFlags, EXC_FONTATTR_ITALIC );
419 1558 : maData.mbStrikeout = ::get_flag( nFlags, EXC_FONTATTR_STRIKEOUT );
420 1558 : maData.mbOutline = ::get_flag( nFlags, EXC_FONTATTR_OUTLINE );
421 1558 : maData.mbShadow = ::get_flag( nFlags, EXC_FONTATTR_SHADOW );
422 1558 : mbHasCharSet = true;
423 1558 : }
424 :
425 1558 : void XclImpFont::ReadFontColor( XclImpStream& rStrm )
426 : {
427 1558 : maData.maColor = GetPalette().GetColor( rStrm.ReaduInt16() );
428 1558 : }
429 :
430 46 : void XclImpFont::ReadFontName2( XclImpStream& rStrm )
431 : {
432 46 : maData.maName = rStrm.ReadByteString( false );
433 46 : }
434 :
435 1512 : void XclImpFont::ReadFontName8( XclImpStream& rStrm )
436 : {
437 1512 : maData.maName = rStrm.ReadUniString( rStrm.ReaduInt8() );
438 1512 : }
439 :
440 2102 : void XclImpFont::GuessScriptType()
441 : {
442 2102 : mbHasWstrn = true;
443 2102 : mbHasAsian = mbHasCmplx = false;
444 :
445 : // find the script types for which the font contains characters
446 2102 : if( OutputDevice* pPrinter = GetPrinter() )
447 : {
448 2102 : vcl::Font aFont( maData.maName, Size( 0, 10 ) );
449 4204 : FontCharMapPtr pCharMap;
450 :
451 2102 : pPrinter->SetFont( aFont );
452 2102 : if( pPrinter->GetFontCharMap( pCharMap ) )
453 : {
454 : // CJK fonts
455 : mbHasAsian =
456 4204 : pCharMap->HasChar( 0x3041 ) || // 3040-309F: Hiragana
457 4204 : pCharMap->HasChar( 0x30A1 ) || // 30A0-30FF: Katakana
458 4204 : pCharMap->HasChar( 0x3111 ) || // 3100-312F: Bopomofo
459 4204 : pCharMap->HasChar( 0x3131 ) || // 3130-318F: Hangul Compatibility Jamo
460 4204 : pCharMap->HasChar( 0x3301 ) || // 3300-33FF: CJK Compatibility
461 4204 : pCharMap->HasChar( 0x3401 ) || // 3400-4DBF: CJK Unified Ideographs Extension A
462 4204 : pCharMap->HasChar( 0x4E01 ) || // 4E00-9FAF: CJK Unified Ideographs
463 4204 : pCharMap->HasChar( 0x7E01 ) || // 4E00-9FAF: CJK unified ideographs
464 4204 : pCharMap->HasChar( 0xA001 ) || // A001-A48F: Yi Syllables
465 4204 : pCharMap->HasChar( 0xAC01 ) || // AC00-D7AF: Hangul Syllables
466 4204 : pCharMap->HasChar( 0xCC01 ) || // AC00-D7AF: Hangul Syllables
467 6306 : pCharMap->HasChar( 0xF901 ) || // F900-FAFF: CJK Compatibility Ideographs
468 4204 : pCharMap->HasChar( 0xFF71 ); // FF00-FFEF: Halfwidth/Fullwidth Forms
469 : // CTL fonts
470 : mbHasCmplx =
471 2678 : pCharMap->HasChar( 0x05D1 ) || // 0590-05FF: Hebrew
472 1152 : pCharMap->HasChar( 0x0631 ) || // 0600-06FF: Arabic
473 1152 : pCharMap->HasChar( 0x0721 ) || // 0700-074F: Syriac
474 1152 : pCharMap->HasChar( 0x0911 ) || // 0900-0DFF: Indic scripts
475 1152 : pCharMap->HasChar( 0x0E01 ) || // 0E00-0E7F: Thai
476 1152 : pCharMap->HasChar( 0xFB21 ) || // FB1D-FB4F: Hebrew Presentation Forms
477 3254 : pCharMap->HasChar( 0xFB51 ) || // FB50-FDFF: Arabic Presentation Forms-A
478 2678 : pCharMap->HasChar( 0xFE71 ); // FE70-FEFF: Arabic Presentation Forms-B
479 : // Western fonts
480 2102 : mbHasWstrn = (!mbHasAsian && !mbHasCmplx) || pCharMap->HasChar( 'A' );
481 : }
482 :
483 4204 : pCharMap = 0;
484 : }
485 2102 : }
486 :
487 144 : XclImpFontBuffer::XclImpFontBuffer( const XclImpRoot& rRoot ) :
488 : XclImpRoot( rRoot ),
489 : maFont4( rRoot ),
490 144 : maCtrlFont( rRoot )
491 : {
492 144 : Initialize();
493 :
494 : // default font for form controls without own font information
495 144 : XclFontData aCtrlFontData;
496 144 : switch( GetBiff() )
497 : {
498 : case EXC_BIFF2:
499 : case EXC_BIFF3:
500 : case EXC_BIFF4:
501 : case EXC_BIFF5:
502 2 : aCtrlFontData.maName = "Helv";
503 2 : aCtrlFontData.mnHeight = 160;
504 2 : aCtrlFontData.mnWeight = EXC_FONTWGHT_BOLD;
505 2 : break;
506 : case EXC_BIFF8:
507 142 : aCtrlFontData.maName = "Tahoma";
508 142 : aCtrlFontData.mnHeight = 160;
509 142 : aCtrlFontData.mnWeight = EXC_FONTWGHT_NORMAL;
510 142 : break;
511 : default:
512 : DBG_ERROR_BIFF();
513 : }
514 144 : maCtrlFont.SetFontData( aCtrlFontData, false );
515 144 : }
516 :
517 144 : void XclImpFontBuffer::Initialize()
518 : {
519 144 : maFontList.clear();
520 :
521 : // application font for column width calculation, later filled with first font from font list
522 144 : XclFontData aAppFontData;
523 144 : aAppFontData.maName = "Arial";
524 144 : aAppFontData.mnHeight = 200;
525 144 : aAppFontData.mnWeight = EXC_FONTWGHT_NORMAL;
526 144 : UpdateAppFont( aAppFontData, false );
527 144 : }
528 :
529 30062 : const XclImpFont* XclImpFontBuffer::GetFont( sal_uInt16 nFontIndex ) const
530 : {
531 : /* Font with index 4 is not stored in an Excel file, but used e.g. by
532 : BIFF5 form pushbutton objects. It is the bold default font.
533 : This also means that entries above 4 are out by one in the list. */
534 :
535 30062 : if (nFontIndex == 4)
536 0 : return &maFont4;
537 :
538 30062 : if (nFontIndex < 4)
539 : {
540 : // Font ID is zero-based when it's less than 4.
541 18950 : return nFontIndex >= maFontList.size() ? NULL : &maFontList[nFontIndex];
542 : }
543 :
544 : // Font ID is greater than 4. It is now 1-based.
545 11112 : return nFontIndex > maFontList.size() ? NULL : &maFontList[nFontIndex-1];
546 : }
547 :
548 1558 : void XclImpFontBuffer::ReadFont( XclImpStream& rStrm )
549 : {
550 1558 : XclImpFont* pFont = new XclImpFont( GetRoot() );
551 1558 : pFont->ReadFont( rStrm );
552 1558 : maFontList.push_back( pFont );
553 :
554 1558 : if( maFontList.size() == 1 )
555 : {
556 140 : UpdateAppFont( pFont->GetFontData(), pFont->HasCharSet() );
557 : // #i71033# set text encoding from application font, if CODEPAGE is missing
558 140 : SetAppFontEncoding( pFont->GetFontEncoding() );
559 : }
560 1558 : }
561 :
562 0 : void XclImpFontBuffer::ReadEfont( XclImpStream& rStrm )
563 : {
564 0 : if( !maFontList.empty() )
565 0 : maFontList.back().ReadEfont( rStrm );
566 0 : }
567 :
568 2766 : void XclImpFontBuffer::FillToItemSet(
569 : SfxItemSet& rItemSet, XclFontItemType eType,
570 : sal_uInt16 nFontIdx, bool bSkipPoolDefs ) const
571 : {
572 2766 : if( const XclImpFont* pFont = GetFont( nFontIdx ) )
573 2766 : pFont->FillToItemSet( rItemSet, eType, bSkipPoolDefs );
574 2766 : }
575 :
576 398 : void XclImpFontBuffer::WriteFontProperties( ScfPropertySet& rPropSet,
577 : XclFontPropSetType eType, sal_uInt16 nFontIdx, const Color* pFontColor ) const
578 : {
579 398 : if( const XclImpFont* pFont = GetFont( nFontIdx ) )
580 398 : pFont->WriteFontProperties( rPropSet, eType, pFontColor );
581 398 : }
582 :
583 0 : void XclImpFontBuffer::WriteDefaultCtrlFontProperties( ScfPropertySet& rPropSet ) const
584 : {
585 0 : maCtrlFont.WriteFontProperties( rPropSet, EXC_FONTPROPSET_CONTROL );
586 0 : }
587 :
588 284 : void XclImpFontBuffer::UpdateAppFont( const XclFontData& rFontData, bool bHasCharSet )
589 : {
590 284 : maAppFont = rFontData;
591 : // #i3006# Calculate the width of '0' from first font and current printer.
592 284 : SetCharWidth( maAppFont );
593 :
594 : // font 4 is bold font 0
595 284 : XclFontData aFont4Data( maAppFont );
596 284 : aFont4Data.mnWeight = EXC_FONTWGHT_BOLD;
597 284 : maFont4.SetFontData( aFont4Data, bHasCharSet );
598 284 : }
599 :
600 : // FORMAT record - number formats =============================================
601 :
602 144 : XclImpNumFmtBuffer::XclImpNumFmtBuffer( const XclImpRoot& rRoot ) :
603 : XclNumFmtBuffer( rRoot ),
604 : XclImpRoot( rRoot ),
605 144 : mnNextXclIdx( 0 )
606 : {
607 144 : }
608 :
609 0 : void XclImpNumFmtBuffer::Initialize()
610 : {
611 0 : maIndexMap.clear();
612 0 : mnNextXclIdx = 0;
613 0 : InitializeImport(); // base class
614 0 : }
615 :
616 1644 : void XclImpNumFmtBuffer::ReadFormat( XclImpStream& rStrm )
617 : {
618 1644 : OUString aFormat;
619 1644 : switch( GetBiff() )
620 : {
621 : case EXC_BIFF2:
622 : case EXC_BIFF3:
623 0 : aFormat = rStrm.ReadByteString( false );
624 0 : break;
625 :
626 : case EXC_BIFF4:
627 0 : rStrm.Ignore( 2 ); // in BIFF4 the index field exists, but is undefined
628 0 : aFormat = rStrm.ReadByteString( false );
629 0 : break;
630 :
631 : case EXC_BIFF5:
632 16 : rStrm >> mnNextXclIdx;
633 16 : aFormat = rStrm.ReadByteString( false );
634 16 : break;
635 :
636 : case EXC_BIFF8:
637 1628 : rStrm >> mnNextXclIdx;
638 1628 : aFormat = rStrm.ReadUniString();
639 1628 : break;
640 :
641 : default:
642 : DBG_ERROR_BIFF();
643 1644 : return;
644 : }
645 :
646 1644 : if( mnNextXclIdx < 0xFFFF )
647 : {
648 1644 : InsertFormat( mnNextXclIdx, aFormat );
649 1644 : ++mnNextXclIdx;
650 1644 : }
651 : }
652 :
653 0 : sal_uInt16 XclImpNumFmtBuffer::ReadCFFormat( XclImpStream& rStrm, bool bIFmt )
654 : {
655 : // internal number format ?
656 0 : if(bIFmt)
657 : {
658 0 : rStrm.Ignore(1);
659 : sal_uInt8 nIndex;
660 0 : rStrm >> nIndex;
661 0 : return nIndex;
662 : }
663 : else
664 : {
665 0 : OUString aFormat = rStrm.ReadUniString();
666 0 : InsertFormat( mnNextXclIdx, aFormat );
667 0 : ++mnNextXclIdx;
668 0 : return mnNextXclIdx - 1;
669 : }
670 : }
671 :
672 142 : void XclImpNumFmtBuffer::CreateScFormats()
673 : {
674 : OSL_ENSURE( maIndexMap.empty(), "XclImpNumFmtBuffer::CreateScFormats - already created" );
675 :
676 142 : SvNumberFormatter& rFormatter = GetFormatter();
677 12278 : for( XclNumFmtMap::const_iterator aIt = GetFormatMap().begin(), aEnd = GetFormatMap().end(); aIt != aEnd; ++aIt )
678 : {
679 12136 : const XclNumFmt& rNumFmt = aIt->second;
680 :
681 : // insert/convert the Excel number format
682 : sal_Int32 nCheckPos;
683 12136 : short nType = NUMBERFORMAT_DEFINED;
684 : sal_uInt32 nKey;
685 12136 : if( !rNumFmt.maFormat.isEmpty() )
686 : {
687 8886 : OUString aFormat( rNumFmt.maFormat );
688 : rFormatter.PutandConvertEntry( aFormat, nCheckPos,
689 8886 : nType, nKey, LANGUAGE_ENGLISH_US, rNumFmt.meLanguage );
690 : }
691 : else
692 3250 : nKey = rFormatter.GetFormatIndex( rNumFmt.meOffset, rNumFmt.meLanguage );
693 :
694 : // insert the resulting format key into the Excel->Calc index map
695 12136 : maIndexMap[ aIt->first ] = nKey;
696 : }
697 142 : }
698 :
699 1496 : sal_uLong XclImpNumFmtBuffer::GetScFormat( sal_uInt16 nXclNumFmt ) const
700 : {
701 1496 : XclImpIndexMap::const_iterator aIt = maIndexMap.find( nXclNumFmt );
702 1496 : return (aIt != maIndexMap.end()) ? aIt->second : NUMBERFORMAT_ENTRY_NOT_FOUND;
703 : }
704 :
705 1318 : void XclImpNumFmtBuffer::FillToItemSet( SfxItemSet& rItemSet, sal_uInt16 nXclNumFmt, bool bSkipPoolDefs ) const
706 : {
707 1318 : sal_uLong nScNumFmt = GetScFormat( nXclNumFmt );
708 1318 : if( nScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND )
709 0 : nScNumFmt = GetStdScNumFmt();
710 1318 : FillScFmtToItemSet( rItemSet, nScNumFmt, bSkipPoolDefs );
711 1318 : }
712 :
713 1320 : void XclImpNumFmtBuffer::FillScFmtToItemSet( SfxItemSet& rItemSet, sal_uLong nScNumFmt, bool bSkipPoolDefs ) const
714 : {
715 : OSL_ENSURE( nScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND, "XclImpNumFmtBuffer::FillScFmtToItemSet - invalid number format" );
716 1320 : ScfTools::PutItem( rItemSet, SfxUInt32Item( ATTR_VALUE_FORMAT, nScNumFmt ), bSkipPoolDefs );
717 1320 : if( rItemSet.GetItemState( ATTR_VALUE_FORMAT, false ) == SfxItemState::SET )
718 1196 : ScGlobal::AddLanguage( rItemSet, GetFormatter() );
719 1320 : }
720 :
721 : // XF, STYLE record - Cell formatting =========================================
722 :
723 0 : void XclImpCellProt::FillFromXF2( sal_uInt8 nNumFmt )
724 : {
725 0 : mbLocked = ::get_flag( nNumFmt, EXC_XF2_LOCKED );
726 0 : mbHidden = ::get_flag( nNumFmt, EXC_XF2_HIDDEN );
727 0 : }
728 :
729 7020 : void XclImpCellProt::FillFromXF3( sal_uInt16 nProt )
730 : {
731 7020 : mbLocked = ::get_flag( nProt, EXC_XF_LOCKED );
732 7020 : mbHidden = ::get_flag( nProt, EXC_XF_HIDDEN );
733 7020 : }
734 :
735 224 : void XclImpCellProt::FillToItemSet( SfxItemSet& rItemSet, bool bSkipPoolDefs ) const
736 : {
737 224 : ScfTools::PutItem( rItemSet, ScProtectionAttr( mbLocked, mbHidden ), bSkipPoolDefs );
738 224 : }
739 :
740 0 : void XclImpCellAlign::FillFromXF2( sal_uInt8 nFlags )
741 : {
742 0 : mnHorAlign = ::extract_value< sal_uInt8 >( nFlags, 0, 3 );
743 0 : }
744 :
745 0 : void XclImpCellAlign::FillFromXF3( sal_uInt16 nAlign )
746 : {
747 0 : mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
748 0 : mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK ); // new in BIFF3
749 0 : }
750 :
751 0 : void XclImpCellAlign::FillFromXF4( sal_uInt16 nAlign )
752 : {
753 0 : FillFromXF3( nAlign );
754 0 : mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 2 ); // new in BIFF4
755 0 : mnOrient = ::extract_value< sal_uInt8 >( nAlign, 6, 2 ); // new in BIFF4
756 0 : }
757 :
758 118 : void XclImpCellAlign::FillFromXF5( sal_uInt16 nAlign )
759 : {
760 118 : mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
761 118 : mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 3 );
762 118 : mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK );
763 118 : mnOrient = ::extract_value< sal_uInt8 >( nAlign, 8, 2 );
764 118 : }
765 :
766 6902 : void XclImpCellAlign::FillFromXF8( sal_uInt16 nAlign, sal_uInt16 nMiscAttrib )
767 : {
768 6902 : mnHorAlign = ::extract_value< sal_uInt8 >( nAlign, 0, 3 );
769 6902 : mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 3 );
770 6902 : mbLineBreak = ::get_flag( nAlign, EXC_XF_LINEBREAK );
771 6902 : mnRotation = ::extract_value< sal_uInt8 >( nAlign, 8, 8 ); // new in BIFF8
772 6902 : mnIndent = ::extract_value< sal_uInt8 >( nMiscAttrib, 0, 4 ); // new in BIFF8
773 6902 : mbShrink = ::get_flag( nMiscAttrib, EXC_XF8_SHRINK ); // new in BIFF8
774 6902 : mnTextDir = ::extract_value< sal_uInt8 >( nMiscAttrib, 6, 2 ); // new in BIFF8
775 6902 : }
776 :
777 0 : void XclImpCellAlign::FillFromCF( sal_uInt16 nAlign, sal_uInt16 nMiscAttrib )
778 : {
779 0 : mnHorAlign = extract_value< sal_uInt8 >( nAlign, 0, 3 );
780 0 : mbLineBreak = get_flag< sal_uInt8 >( nAlign, EXC_XF_LINEBREAK );
781 0 : mnVerAlign = ::extract_value< sal_uInt8 >( nAlign, 4, 3 );
782 0 : mnRotation = ::extract_value< sal_uInt8 >( nAlign, 8, 8 );
783 0 : mnIndent = ::extract_value< sal_uInt8 >( nMiscAttrib, 0, 4 );
784 0 : mbShrink = ::get_flag( nMiscAttrib, EXC_XF8_SHRINK );
785 0 : mnTextDir = ::extract_value< sal_uInt8 >( nMiscAttrib, 6, 2 );
786 0 : }
787 :
788 1944 : void XclImpCellAlign::FillToItemSet( SfxItemSet& rItemSet, const XclImpFont* pFont, bool bSkipPoolDefs ) const
789 : {
790 : // horizontal alignment
791 1944 : ScfTools::PutItem( rItemSet, SvxHorJustifyItem( GetScHorAlign(), ATTR_HOR_JUSTIFY ), bSkipPoolDefs );
792 1944 : ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( GetScHorJustifyMethod(), ATTR_HOR_JUSTIFY_METHOD ), bSkipPoolDefs );
793 :
794 : // text wrap (#i74508# always if vertical alignment is justified or distributed)
795 1944 : bool bLineBreak = mbLineBreak || (mnVerAlign == EXC_XF_VER_JUSTIFY) || (mnVerAlign == EXC_XF_VER_DISTRIB);
796 1944 : ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_LINEBREAK, bLineBreak ), bSkipPoolDefs );
797 :
798 : // vertical alignment
799 1944 : ScfTools::PutItem( rItemSet, SvxVerJustifyItem( GetScVerAlign(), ATTR_VER_JUSTIFY ), bSkipPoolDefs );
800 1944 : ScfTools::PutItem( rItemSet, SvxJustifyMethodItem( GetScVerJustifyMethod(), ATTR_VER_JUSTIFY_METHOD ), bSkipPoolDefs );
801 :
802 : // indent
803 1944 : sal_uInt16 nScIndent = mnIndent * 200; // 1 Excel unit == 10 pt == 200 twips
804 1944 : ScfTools::PutItem( rItemSet, SfxUInt16Item( ATTR_INDENT, nScIndent ), bSkipPoolDefs );
805 :
806 : // shrink to fit
807 1944 : ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_SHRINKTOFIT, mbShrink ), bSkipPoolDefs );
808 :
809 : // text orientation/rotation (BIFF2-BIFF7 sets mnOrient)
810 1944 : sal_uInt8 nXclRot = (mnOrient == EXC_ORIENT_NONE) ? mnRotation : XclTools::GetXclRotFromOrient( mnOrient );
811 1944 : bool bStacked = (nXclRot == EXC_ROT_STACKED);
812 1944 : ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_STACKED, bStacked ), bSkipPoolDefs );
813 : // set an angle in the range from -90 to 90 degrees
814 1944 : sal_Int32 nAngle = XclTools::GetScRotation( nXclRot, 0 );
815 1944 : ScfTools::PutItem( rItemSet, SfxInt32Item( ATTR_ROTATE_VALUE, nAngle ), bSkipPoolDefs );
816 : // set "Use asian vertical layout", if cell is stacked and font contains CKJ characters
817 1944 : bool bAsianVert = bStacked && pFont && pFont->HasAsianChars();
818 1944 : ScfTools::PutItem( rItemSet, SfxBoolItem( ATTR_VERTICAL_ASIAN, bAsianVert ), bSkipPoolDefs );
819 :
820 : // CTL text direction
821 1944 : ScfTools::PutItem( rItemSet, SvxFrameDirectionItem( GetScFrameDir(), ATTR_WRITINGDIR ), bSkipPoolDefs );
822 1944 : }
823 :
824 7020 : XclImpCellBorder::XclImpCellBorder()
825 : {
826 7020 : SetUsedFlags( false, false );
827 7020 : }
828 :
829 14040 : void XclImpCellBorder::SetUsedFlags( bool bOuterUsed, bool bDiagUsed )
830 : {
831 14040 : mbLeftUsed = mbRightUsed = mbTopUsed = mbBottomUsed = bOuterUsed;
832 14040 : mbDiagUsed = bDiagUsed;
833 14040 : }
834 :
835 0 : void XclImpCellBorder::FillFromXF2( sal_uInt8 nFlags )
836 : {
837 0 : mnLeftLine = ::get_flagvalue( nFlags, EXC_XF2_LEFTLINE, EXC_LINE_THIN, EXC_LINE_NONE );
838 0 : mnRightLine = ::get_flagvalue( nFlags, EXC_XF2_RIGHTLINE, EXC_LINE_THIN, EXC_LINE_NONE );
839 0 : mnTopLine = ::get_flagvalue( nFlags, EXC_XF2_TOPLINE, EXC_LINE_THIN, EXC_LINE_NONE );
840 0 : mnBottomLine = ::get_flagvalue( nFlags, EXC_XF2_BOTTOMLINE, EXC_LINE_THIN, EXC_LINE_NONE );
841 0 : mnLeftColor = mnRightColor = mnTopColor = mnBottomColor = EXC_COLOR_BIFF2_BLACK;
842 0 : SetUsedFlags( true, false );
843 0 : }
844 :
845 0 : void XclImpCellBorder::FillFromXF3( sal_uInt32 nBorder )
846 : {
847 0 : mnTopLine = ::extract_value< sal_uInt8 >( nBorder, 0, 3 );
848 0 : mnLeftLine = ::extract_value< sal_uInt8 >( nBorder, 8, 3 );
849 0 : mnBottomLine = ::extract_value< sal_uInt8 >( nBorder, 16, 3 );
850 0 : mnRightLine = ::extract_value< sal_uInt8 >( nBorder, 24, 3 );
851 0 : mnTopColor = ::extract_value< sal_uInt16 >( nBorder, 3, 5 );
852 0 : mnLeftColor = ::extract_value< sal_uInt16 >( nBorder, 11, 5 );
853 0 : mnBottomColor = ::extract_value< sal_uInt16 >( nBorder, 19, 5 );
854 0 : mnRightColor = ::extract_value< sal_uInt16 >( nBorder, 27, 5 );
855 0 : SetUsedFlags( true, false );
856 0 : }
857 :
858 118 : void XclImpCellBorder::FillFromXF5( sal_uInt32 nBorder, sal_uInt32 nArea )
859 : {
860 118 : mnTopLine = ::extract_value< sal_uInt8 >( nBorder, 0, 3 );
861 118 : mnLeftLine = ::extract_value< sal_uInt8 >( nBorder, 3, 3 );
862 118 : mnBottomLine = ::extract_value< sal_uInt8 >( nArea, 22, 3 );
863 118 : mnRightLine = ::extract_value< sal_uInt8 >( nBorder, 6, 3 );
864 118 : mnTopColor = ::extract_value< sal_uInt16 >( nBorder, 9, 7 );
865 118 : mnLeftColor = ::extract_value< sal_uInt16 >( nBorder, 16, 7 );
866 118 : mnBottomColor = ::extract_value< sal_uInt16 >( nArea, 25, 7 );
867 118 : mnRightColor = ::extract_value< sal_uInt16 >( nBorder, 23, 7 );
868 118 : SetUsedFlags( true, false );
869 118 : }
870 :
871 6902 : void XclImpCellBorder::FillFromXF8( sal_uInt32 nBorder1, sal_uInt32 nBorder2 )
872 : {
873 6902 : mnLeftLine = ::extract_value< sal_uInt8 >( nBorder1, 0, 4 );
874 6902 : mnRightLine = ::extract_value< sal_uInt8 >( nBorder1, 4, 4 );
875 6902 : mnTopLine = ::extract_value< sal_uInt8 >( nBorder1, 8, 4 );
876 6902 : mnBottomLine = ::extract_value< sal_uInt8 >( nBorder1, 12, 4 );
877 6902 : mnLeftColor = ::extract_value< sal_uInt16 >( nBorder1, 16, 7 );
878 6902 : mnRightColor = ::extract_value< sal_uInt16 >( nBorder1, 23, 7 );
879 6902 : mnTopColor = ::extract_value< sal_uInt16 >( nBorder2, 0, 7 );
880 6902 : mnBottomColor = ::extract_value< sal_uInt16 >( nBorder2, 7, 7 );
881 6902 : mbDiagTLtoBR = ::get_flag( nBorder1, EXC_XF_DIAGONAL_TL_TO_BR );
882 6902 : mbDiagBLtoTR = ::get_flag( nBorder1, EXC_XF_DIAGONAL_BL_TO_TR );
883 6902 : if( mbDiagTLtoBR || mbDiagBLtoTR )
884 : {
885 0 : mnDiagLine = ::extract_value< sal_uInt8 >( nBorder2, 21, 4 );
886 0 : mnDiagColor = ::extract_value< sal_uInt16 >( nBorder2, 14, 7 );
887 : }
888 6902 : SetUsedFlags( true, true );
889 6902 : }
890 :
891 0 : void XclImpCellBorder::FillFromCF8( sal_uInt16 nLineStyle, sal_uInt32 nLineColor, sal_uInt32 nFlags )
892 : {
893 0 : mnLeftLine = ::extract_value< sal_uInt8 >( nLineStyle, 0, 4 );
894 0 : mnRightLine = ::extract_value< sal_uInt8 >( nLineStyle, 4, 4 );
895 0 : mnTopLine = ::extract_value< sal_uInt8 >( nLineStyle, 8, 4 );
896 0 : mnBottomLine = ::extract_value< sal_uInt8 >( nLineStyle, 12, 4 );
897 0 : mnLeftColor = ::extract_value< sal_uInt16 >( nLineColor, 0, 7 );
898 0 : mnRightColor = ::extract_value< sal_uInt16 >( nLineColor, 7, 7 );
899 0 : mnTopColor = ::extract_value< sal_uInt16 >( nLineColor, 16, 7 );
900 0 : mnBottomColor = ::extract_value< sal_uInt16 >( nLineColor, 23, 7 );
901 0 : mbLeftUsed = !::get_flag( nFlags, EXC_CF_BORDER_LEFT );
902 0 : mbRightUsed = !::get_flag( nFlags, EXC_CF_BORDER_RIGHT );
903 0 : mbTopUsed = !::get_flag( nFlags, EXC_CF_BORDER_TOP );
904 0 : mbBottomUsed = !::get_flag( nFlags, EXC_CF_BORDER_BOTTOM );
905 0 : mbDiagUsed = false;
906 0 : }
907 :
908 10 : bool XclImpCellBorder::HasAnyOuterBorder() const
909 : {
910 : return
911 10 : (mbLeftUsed && (mnLeftLine != EXC_LINE_NONE)) ||
912 4 : (mbRightUsed && (mnRightLine != EXC_LINE_NONE)) ||
913 20 : (mbTopUsed && (mnTopLine != EXC_LINE_NONE)) ||
914 14 : (mbBottomUsed && (mnBottomLine != EXC_LINE_NONE));
915 : }
916 :
917 : namespace {
918 :
919 : /** Converts the passed line style to a ::editeng::SvxBorderLine, or returns false, if style is "no line". */
920 12578 : bool lclConvertBorderLine( ::editeng::SvxBorderLine& rLine, const XclImpPalette& rPalette, sal_uInt8 nXclLine, sal_uInt16 nXclColor )
921 : {
922 : static const sal_uInt16 ppnLineParam[][ 4 ] =
923 : {
924 : // outer width, type
925 : { 0, table::BorderLineStyle::SOLID }, // 0 = none
926 : { EXC_BORDER_THIN, table::BorderLineStyle::SOLID }, // 1 = thin
927 : { EXC_BORDER_MEDIUM, table::BorderLineStyle::SOLID }, // 2 = medium
928 : { EXC_BORDER_THIN, table::BorderLineStyle::FINE_DASHED }, // 3 = dashed
929 : { EXC_BORDER_THIN, table::BorderLineStyle::DOTTED }, // 4 = dotted
930 : { EXC_BORDER_THICK, table::BorderLineStyle::SOLID }, // 5 = thick
931 : { EXC_BORDER_THICK, table::BorderLineStyle::DOUBLE_THIN }, // 6 = double
932 : { EXC_BORDER_HAIR, table::BorderLineStyle::SOLID }, // 7 = hair
933 : { EXC_BORDER_MEDIUM, table::BorderLineStyle::DASHED }, // 8 = med dash
934 : { EXC_BORDER_THIN, table::BorderLineStyle::DASH_DOT }, // 9 = thin dashdot
935 : { EXC_BORDER_MEDIUM, table::BorderLineStyle::DASH_DOT }, // A = med dashdot
936 : { EXC_BORDER_THIN, table::BorderLineStyle::DASH_DOT_DOT }, // B = thin dashdotdot
937 : { EXC_BORDER_MEDIUM, table::BorderLineStyle::DASH_DOT_DOT }, // C = med dashdotdot
938 : { EXC_BORDER_MEDIUM, table::BorderLineStyle::DASH_DOT } // D = med slant dashdot
939 : };
940 :
941 12578 : if( nXclLine == EXC_LINE_NONE )
942 4756 : return false;
943 7822 : if( nXclLine >= SAL_N_ELEMENTS( ppnLineParam ) )
944 0 : nXclLine = EXC_LINE_THIN;
945 :
946 7822 : rLine.SetColor( rPalette.GetColor( nXclColor ) );
947 7822 : rLine.SetWidth( ppnLineParam[ nXclLine ][ 0 ] );
948 : rLine.SetBorderLineStyle( static_cast< ::editeng::SvxBorderStyle>(
949 7822 : ppnLineParam[ nXclLine ][ 1 ]) );
950 7822 : return true;
951 : }
952 :
953 : } // namespace
954 :
955 2520 : void XclImpCellBorder::FillToItemSet( SfxItemSet& rItemSet, const XclImpPalette& rPalette, bool bSkipPoolDefs ) const
956 : {
957 2520 : if( mbLeftUsed || mbRightUsed || mbTopUsed || mbBottomUsed )
958 : {
959 2520 : SvxBoxItem aBoxItem( ATTR_BORDER );
960 2520 : ::editeng::SvxBorderLine aLine;
961 2520 : if( mbLeftUsed && lclConvertBorderLine( aLine, rPalette, mnLeftLine, mnLeftColor ) )
962 1876 : aBoxItem.SetLine( &aLine, BOX_LINE_LEFT );
963 2520 : if( mbRightUsed && lclConvertBorderLine( aLine, rPalette, mnRightLine, mnRightColor ) )
964 1844 : aBoxItem.SetLine( &aLine, BOX_LINE_RIGHT );
965 2520 : if( mbTopUsed && lclConvertBorderLine( aLine, rPalette, mnTopLine, mnTopColor ) )
966 2054 : aBoxItem.SetLine( &aLine, BOX_LINE_TOP );
967 2520 : if( mbBottomUsed && lclConvertBorderLine( aLine, rPalette, mnBottomLine, mnBottomColor ) )
968 2048 : aBoxItem.SetLine( &aLine, BOX_LINE_BOTTOM );
969 2520 : ScfTools::PutItem( rItemSet, aBoxItem, bSkipPoolDefs );
970 : }
971 2520 : if( mbDiagUsed )
972 : {
973 2498 : SvxLineItem aTLBRItem( ATTR_BORDER_TLBR );
974 4996 : SvxLineItem aBLTRItem( ATTR_BORDER_BLTR );
975 2498 : ::editeng::SvxBorderLine aLine;
976 2498 : if( lclConvertBorderLine( aLine, rPalette, mnDiagLine, mnDiagColor ) )
977 : {
978 0 : if( mbDiagTLtoBR )
979 0 : aTLBRItem.SetLine( &aLine );
980 0 : if( mbDiagBLtoTR )
981 0 : aBLTRItem.SetLine( &aLine );
982 : }
983 2498 : ScfTools::PutItem( rItemSet, aTLBRItem, bSkipPoolDefs );
984 4996 : ScfTools::PutItem( rItemSet, aBLTRItem, bSkipPoolDefs );
985 : }
986 2520 : }
987 :
988 7020 : XclImpCellArea::XclImpCellArea()
989 : {
990 7020 : SetUsedFlags( false );
991 7020 : }
992 :
993 14040 : void XclImpCellArea::SetUsedFlags( bool bUsed )
994 : {
995 14040 : mbForeUsed = mbBackUsed = mbPattUsed = bUsed;
996 14040 : }
997 :
998 0 : void XclImpCellArea::FillFromXF2( sal_uInt8 nFlags )
999 : {
1000 0 : mnPattern = ::get_flagvalue( nFlags, EXC_XF2_BACKGROUND, EXC_PATT_12_5_PERC, EXC_PATT_NONE );
1001 0 : mnForeColor = EXC_COLOR_BIFF2_BLACK;
1002 0 : mnBackColor = EXC_COLOR_BIFF2_WHITE;
1003 0 : SetUsedFlags( true );
1004 0 : }
1005 :
1006 0 : void XclImpCellArea::FillFromXF3( sal_uInt16 nArea )
1007 : {
1008 0 : mnPattern = ::extract_value< sal_uInt8 >( nArea, 0, 6 );
1009 0 : mnForeColor = ::extract_value< sal_uInt16 >( nArea, 6, 5 );
1010 0 : mnBackColor = ::extract_value< sal_uInt16 >( nArea, 11, 5 );
1011 0 : SetUsedFlags( true );
1012 0 : }
1013 :
1014 118 : void XclImpCellArea::FillFromXF5( sal_uInt32 nArea )
1015 : {
1016 118 : mnPattern = ::extract_value< sal_uInt8 >( nArea, 16, 6 );
1017 118 : mnForeColor = ::extract_value< sal_uInt16 >( nArea, 0, 7 );
1018 118 : mnBackColor = ::extract_value< sal_uInt16 >( nArea, 7, 7 );
1019 118 : SetUsedFlags( true );
1020 118 : }
1021 :
1022 6902 : void XclImpCellArea::FillFromXF8( sal_uInt32 nBorder2, sal_uInt16 nArea )
1023 : {
1024 6902 : mnPattern = ::extract_value< sal_uInt8 >( nBorder2, 26, 6 );
1025 6902 : mnForeColor = ::extract_value< sal_uInt16 >( nArea, 0, 7 );
1026 6902 : mnBackColor = ::extract_value< sal_uInt16 >( nArea, 7, 7 );
1027 6902 : SetUsedFlags( true );
1028 6902 : }
1029 :
1030 0 : void XclImpCellArea::FillFromCF8( sal_uInt16 nPattern, sal_uInt16 nColor, sal_uInt32 nFlags )
1031 : {
1032 0 : mnForeColor = ::extract_value< sal_uInt16 >( nColor, 0, 7 );
1033 0 : mnBackColor = ::extract_value< sal_uInt16 >( nColor, 7, 7 );
1034 0 : mnPattern = ::extract_value< sal_uInt8 >( nPattern, 10, 6 );
1035 0 : mbForeUsed = !::get_flag( nFlags, EXC_CF_AREA_FGCOLOR );
1036 0 : mbBackUsed = !::get_flag( nFlags, EXC_CF_AREA_BGCOLOR );
1037 0 : mbPattUsed = !::get_flag( nFlags, EXC_CF_AREA_PATTERN );
1038 :
1039 0 : if( mbBackUsed && (!mbPattUsed || (mnPattern == EXC_PATT_SOLID)) )
1040 : {
1041 0 : mnForeColor = mnBackColor;
1042 0 : mnPattern = EXC_PATT_SOLID;
1043 0 : mbForeUsed = mbPattUsed = true;
1044 : }
1045 0 : else if( !mbBackUsed && mbPattUsed && (mnPattern == EXC_PATT_SOLID) )
1046 : {
1047 0 : mbPattUsed = false;
1048 : }
1049 0 : }
1050 :
1051 2696 : void XclImpCellArea::FillToItemSet( SfxItemSet& rItemSet, const XclImpPalette& rPalette, bool bSkipPoolDefs ) const
1052 : {
1053 2696 : if( mbPattUsed ) // colors may be both unused in cond. formats
1054 : {
1055 2696 : SvxBrushItem aBrushItem( ATTR_BACKGROUND );
1056 :
1057 : // do not use IsTransparent() - old Calc filter writes tranparency with different color indexes
1058 2696 : if( mnPattern == EXC_PATT_NONE )
1059 : {
1060 228 : aBrushItem.SetColor( Color( COL_TRANSPARENT ) );
1061 : }
1062 : else
1063 : {
1064 2468 : Color aFore( rPalette.GetColor( mbForeUsed ? mnForeColor : EXC_COLOR_WINDOWTEXT ) );
1065 2468 : Color aBack( rPalette.GetColor( mbBackUsed ? mnBackColor : EXC_COLOR_WINDOWBACK ) );
1066 2468 : aBrushItem.SetColor( XclTools::GetPatternColor( aFore, aBack, mnPattern ) );
1067 : }
1068 :
1069 2696 : ScfTools::PutItem( rItemSet, aBrushItem, bSkipPoolDefs );
1070 : }
1071 2696 : }
1072 :
1073 7020 : XclImpXF::XclImpXF( const XclImpRoot& rRoot ) :
1074 : XclXFBase( true ), // default is cell XF
1075 : XclImpRoot( rRoot ),
1076 : mpStyleSheet( 0 ),
1077 : mnXclNumFmt( 0 ),
1078 7020 : mnXclFont( 0 )
1079 : {
1080 7020 : }
1081 :
1082 14040 : XclImpXF::~XclImpXF()
1083 : {
1084 14040 : }
1085 :
1086 0 : void XclImpXF::ReadXF2( XclImpStream& rStrm )
1087 : {
1088 : sal_uInt8 nReadFont, nReadNumFmt, nFlags;
1089 0 : rStrm >> nReadFont;
1090 0 : rStrm.Ignore( 1 );
1091 0 : rStrm >> nReadNumFmt >> nFlags;
1092 :
1093 : // XF type always cell, no parent, used flags always true
1094 0 : SetAllUsedFlags( true );
1095 :
1096 : // attributes
1097 0 : maProtection.FillFromXF2( nReadNumFmt );
1098 0 : mnXclFont = nReadFont;
1099 0 : mnXclNumFmt = nReadNumFmt & EXC_XF2_VALFMT_MASK;
1100 0 : maAlignment.FillFromXF2( nFlags );
1101 0 : maBorder.FillFromXF2( nFlags );
1102 0 : maArea.FillFromXF2( nFlags );
1103 0 : }
1104 :
1105 0 : void XclImpXF::ReadXF3( XclImpStream& rStrm )
1106 : {
1107 : sal_uInt32 nBorder;
1108 : sal_uInt16 nTypeProt, nAlign, nArea;
1109 : sal_uInt8 nReadFont, nReadNumFmt;
1110 0 : rStrm >> nReadFont >> nReadNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1111 :
1112 : // XF type/parent, attribute used flags
1113 0 : mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE ); // new in BIFF3
1114 0 : mnParent = ::extract_value< sal_uInt16 >( nAlign, 4, 12 ); // new in BIFF3
1115 0 : SetUsedFlags( ::extract_value< sal_uInt8 >( nTypeProt, 10, 6 ) );
1116 :
1117 : // attributes
1118 0 : maProtection.FillFromXF3( nTypeProt );
1119 0 : mnXclFont = nReadFont;
1120 0 : mnXclNumFmt = nReadNumFmt;
1121 0 : maAlignment.FillFromXF3( nAlign );
1122 0 : maBorder.FillFromXF3( nBorder );
1123 0 : maArea.FillFromXF3( nArea ); // new in BIFF3
1124 0 : }
1125 :
1126 0 : void XclImpXF::ReadXF4( XclImpStream& rStrm )
1127 : {
1128 : sal_uInt32 nBorder;
1129 : sal_uInt16 nTypeProt, nAlign, nArea;
1130 : sal_uInt8 nReadFont, nReadNumFmt;
1131 0 : rStrm >> nReadFont >> nReadNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1132 :
1133 : // XF type/parent, attribute used flags
1134 0 : mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1135 0 : mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1136 0 : SetUsedFlags( ::extract_value< sal_uInt8 >( nAlign, 10, 6 ) );
1137 :
1138 : // attributes
1139 0 : maProtection.FillFromXF3( nTypeProt );
1140 0 : mnXclFont = nReadFont;
1141 0 : mnXclNumFmt = nReadNumFmt;
1142 0 : maAlignment.FillFromXF4( nAlign );
1143 0 : maBorder.FillFromXF3( nBorder );
1144 0 : maArea.FillFromXF3( nArea );
1145 0 : }
1146 :
1147 118 : void XclImpXF::ReadXF5( XclImpStream& rStrm )
1148 : {
1149 : sal_uInt32 nArea, nBorder;
1150 : sal_uInt16 nTypeProt, nAlign;
1151 118 : rStrm >> mnXclFont >> mnXclNumFmt >> nTypeProt >> nAlign >> nArea >> nBorder;
1152 :
1153 : // XF type/parent, attribute used flags
1154 118 : mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1155 118 : mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1156 118 : SetUsedFlags( ::extract_value< sal_uInt8 >( nAlign, 10, 6 ) );
1157 :
1158 : // attributes
1159 118 : maProtection.FillFromXF3( nTypeProt );
1160 118 : maAlignment.FillFromXF5( nAlign );
1161 118 : maBorder.FillFromXF5( nBorder, nArea );
1162 118 : maArea.FillFromXF5( nArea );
1163 118 : }
1164 :
1165 6902 : void XclImpXF::ReadXF8( XclImpStream& rStrm )
1166 : {
1167 : sal_uInt32 nBorder1, nBorder2;
1168 : sal_uInt16 nTypeProt, nAlign, nMiscAttrib, nArea;
1169 6902 : rStrm >> mnXclFont >> mnXclNumFmt >> nTypeProt >> nAlign >> nMiscAttrib >> nBorder1 >> nBorder2 >> nArea;
1170 :
1171 : // XF type/parent, attribute used flags
1172 6902 : mbCellXF = !::get_flag( nTypeProt, EXC_XF_STYLE );
1173 6902 : mnParent = ::extract_value< sal_uInt16 >( nTypeProt, 4, 12 );
1174 6902 : SetUsedFlags( ::extract_value< sal_uInt8 >( nMiscAttrib, 10, 6 ) );
1175 :
1176 : // attributes
1177 6902 : maProtection.FillFromXF3( nTypeProt );
1178 6902 : maAlignment.FillFromXF8( nAlign, nMiscAttrib );
1179 6902 : maBorder.FillFromXF8( nBorder1, nBorder2 );
1180 6902 : maArea.FillFromXF8( nBorder2, nArea );
1181 6902 : }
1182 :
1183 7020 : void XclImpXF::ReadXF( XclImpStream& rStrm )
1184 : {
1185 7020 : switch( GetBiff() )
1186 : {
1187 0 : case EXC_BIFF2: ReadXF2( rStrm ); break;
1188 0 : case EXC_BIFF3: ReadXF3( rStrm ); break;
1189 0 : case EXC_BIFF4: ReadXF4( rStrm ); break;
1190 118 : case EXC_BIFF5: ReadXF5( rStrm ); break;
1191 6902 : case EXC_BIFF8: ReadXF8( rStrm ); break;
1192 : default: DBG_ERROR_BIFF();
1193 : }
1194 7020 : }
1195 :
1196 238124 : const ScPatternAttr& XclImpXF::CreatePattern( bool bSkipPoolDefs )
1197 : {
1198 238124 : if( mpPattern.get() )
1199 234482 : return *mpPattern;
1200 :
1201 : // create new pattern attribute set
1202 3642 : mpPattern.reset( new ScPatternAttr( GetDoc().GetPool() ) );
1203 3642 : SfxItemSet& rItemSet = mpPattern->GetItemSet();
1204 3642 : XclImpXF* pParentXF = IsCellXF() ? GetXFBuffer().GetXF( mnParent ) : 0;
1205 :
1206 : // parent cell style
1207 3642 : if( IsCellXF() && !mpStyleSheet )
1208 : {
1209 2658 : mpStyleSheet = GetXFBuffer().CreateStyleSheet( mnParent );
1210 :
1211 : /* Enables mb***Used flags, if the formatting attributes differ from
1212 : the passed XF record. In cell XFs Excel uses the cell attributes,
1213 : if they differ from the parent style XF.
1214 : ...or if the respective flag is not set in parent style XF. */
1215 2658 : if( pParentXF )
1216 : {
1217 2658 : if( !mbProtUsed )
1218 2616 : mbProtUsed = !pParentXF->mbProtUsed || !(maProtection == pParentXF->maProtection);
1219 2658 : if( !mbFontUsed )
1220 1062 : mbFontUsed = !pParentXF->mbFontUsed || (mnXclFont != pParentXF->mnXclFont);
1221 2658 : if( !mbFmtUsed )
1222 1506 : mbFmtUsed = !pParentXF->mbFmtUsed || (mnXclNumFmt != pParentXF->mnXclNumFmt);
1223 2658 : if( !mbAlignUsed )
1224 876 : mbAlignUsed = !pParentXF->mbAlignUsed || !(maAlignment == pParentXF->maAlignment);
1225 2658 : if( !mbBorderUsed )
1226 510 : mbBorderUsed = !pParentXF->mbBorderUsed || !(maBorder == pParentXF->maBorder);
1227 2658 : if( !mbAreaUsed )
1228 780 : mbAreaUsed = !pParentXF->mbAreaUsed || !(maArea == pParentXF->maArea);
1229 : }
1230 : }
1231 :
1232 : // cell protection
1233 3642 : if( mbProtUsed )
1234 224 : maProtection.FillToItemSet( rItemSet, bSkipPoolDefs );
1235 :
1236 : // font
1237 3642 : if( mbFontUsed )
1238 2556 : GetFontBuffer().FillToItemSet( rItemSet, EXC_FONTITEM_CELL, mnXclFont, bSkipPoolDefs );
1239 :
1240 : // value format
1241 3642 : if( mbFmtUsed )
1242 : {
1243 1318 : GetNumFmtBuffer().FillToItemSet( rItemSet, mnXclNumFmt, bSkipPoolDefs );
1244 : // Trace occurrences of Windows date formats
1245 1318 : GetTracer().TraceDates( mnXclNumFmt );
1246 : }
1247 :
1248 : // alignment
1249 3642 : if( mbAlignUsed )
1250 1944 : maAlignment.FillToItemSet( rItemSet, GetFontBuffer().GetFont( mnXclFont ), bSkipPoolDefs );
1251 :
1252 : // border
1253 3642 : if( mbBorderUsed )
1254 : {
1255 2520 : maBorder.FillToItemSet( rItemSet, GetPalette(), bSkipPoolDefs );
1256 7538 : GetTracer().TraceBorderLineStyle(maBorder.mnLeftLine > EXC_LINE_HAIR ||
1257 7494 : maBorder.mnRightLine > EXC_LINE_HAIR || maBorder.mnTopLine > EXC_LINE_HAIR ||
1258 7516 : maBorder.mnBottomLine > EXC_LINE_HAIR );
1259 : }
1260 :
1261 : // area
1262 3642 : if( mbAreaUsed )
1263 : {
1264 2696 : maArea.FillToItemSet( rItemSet, GetPalette(), bSkipPoolDefs );
1265 7860 : GetTracer().TraceFillPattern(maArea.mnPattern != EXC_PATT_NONE &&
1266 7860 : maArea.mnPattern != EXC_PATT_SOLID);
1267 : }
1268 :
1269 : /* #i38709# Decide which rotation reference mode to use. If any outer
1270 : border line of the cell is set (either explicitly or via cell style),
1271 : and the cell contents are rotated, set rotation reference to bottom of
1272 : cell. This causes the borders to be painted rotated with the text. */
1273 3642 : if( mbAlignUsed || mbBorderUsed )
1274 : {
1275 2688 : SvxRotateMode eRotateMode = SVX_ROTATE_MODE_STANDARD;
1276 2688 : const XclImpCellAlign* pAlign = mbAlignUsed ? &maAlignment : (pParentXF ? &pParentXF->maAlignment : 0);
1277 2688 : const XclImpCellBorder* pBorder = mbBorderUsed ? &maBorder : (pParentXF ? &pParentXF->maBorder : 0);
1278 2688 : if( pAlign && pBorder && (0 < pAlign->mnRotation) && (pAlign->mnRotation <= 180) && pBorder->HasAnyOuterBorder() )
1279 6 : eRotateMode = SVX_ROTATE_MODE_BOTTOM;
1280 2688 : ScfTools::PutItem( rItemSet, SvxRotateModeItem( eRotateMode, ATTR_ROTATE_MODE ), bSkipPoolDefs );
1281 : }
1282 :
1283 : // Excel's cell margins are different from Calc's default margins.
1284 3642 : SvxMarginItem aItem(40, 40, 40, 40, ATTR_MARGIN);
1285 3642 : ScfTools::PutItem(rItemSet, aItem, bSkipPoolDefs);
1286 :
1287 3642 : return *mpPattern;
1288 : }
1289 :
1290 237150 : void XclImpXF::ApplyPatternToAttrList(
1291 : list<ScAttrEntry>& rAttrs, SCROW nRow1, SCROW nRow2, sal_uInt32 nForceScNumFmt)
1292 : {
1293 : // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1294 237150 : CreatePattern();
1295 237150 : ScPatternAttr& rPat = *mpPattern;
1296 :
1297 : // insert into document
1298 237150 : ScDocument& rDoc = GetDoc();
1299 :
1300 237150 : if (IsCellXF())
1301 : {
1302 236610 : if (mpStyleSheet)
1303 : {
1304 : // Apply style sheet. Don't clear the direct formats.
1305 236610 : rPat.SetStyleSheet(mpStyleSheet, false);
1306 : }
1307 : else
1308 : {
1309 : // When the cell format is not associated with any style, use the
1310 : // 'Default' style. Some buggy XLS docs generated by apps other
1311 : // than Excel (such as 1C) may not have any built-in styles at
1312 : // all.
1313 0 : ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
1314 0 : if (pStylePool)
1315 : {
1316 : ScStyleSheet* pStyleSheet = static_cast<ScStyleSheet*>(
1317 : pStylePool->Find(
1318 0 : ScGlobal::GetRscString(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PARA));
1319 :
1320 0 : if (pStyleSheet)
1321 0 : rPat.SetStyleSheet(pStyleSheet, false);
1322 : }
1323 :
1324 : }
1325 : }
1326 :
1327 237150 : if (nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND)
1328 : {
1329 2 : ScPatternAttr aNumPat(rDoc.GetPool());
1330 2 : GetNumFmtBuffer().FillScFmtToItemSet(aNumPat.GetItemSet(), nForceScNumFmt);
1331 2 : rPat.GetItemSet().Put(aNumPat.GetItemSet());
1332 : }
1333 :
1334 : // Make sure we skip unnamed styles.
1335 237150 : if (rPat.GetStyleName())
1336 : {
1337 : // Check for a gap between the last entry and this one.
1338 236610 : bool bHasGap = false;
1339 236610 : if (rAttrs.empty() && nRow1 > 0)
1340 : // First attribute range doesn't start at row 0.
1341 17082 : bHasGap = true;
1342 :
1343 236610 : if (!rAttrs.empty() && rAttrs.back().nRow + 1 < nRow1)
1344 33952 : bHasGap = true;
1345 :
1346 236610 : if (bHasGap)
1347 : {
1348 : // Fill this gap with the default pattern.
1349 : ScAttrEntry aEntry;
1350 51034 : aEntry.nRow = nRow1 - 1;
1351 51034 : aEntry.pPattern = rDoc.GetDefPattern();
1352 51034 : rAttrs.push_back(aEntry);
1353 : }
1354 :
1355 : ScAttrEntry aEntry;
1356 236610 : aEntry.nRow = nRow2;
1357 236610 : aEntry.pPattern = static_cast<const ScPatternAttr*>(&rDoc.GetPool()->Put(rPat));
1358 236610 : rAttrs.push_back(aEntry);
1359 : }
1360 237150 : }
1361 :
1362 0 : void XclImpXF::ApplyPattern(
1363 : SCCOL nScCol1, SCROW nScRow1, SCCOL nScCol2, SCROW nScRow2,
1364 : SCTAB nScTab, sal_uLong nForceScNumFmt )
1365 : {
1366 : // force creation of cell style and hard formatting, do it here to have mpStyleSheet
1367 0 : const ScPatternAttr& rPattern = CreatePattern();
1368 :
1369 : // insert into document
1370 0 : ScDocument& rDoc = GetDoc();
1371 0 : if( IsCellXF() && mpStyleSheet )
1372 0 : rDoc.ApplyStyleAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, *mpStyleSheet );
1373 0 : if( HasUsedFlags() )
1374 0 : rDoc.ApplyPatternAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, rPattern );
1375 :
1376 : // #108770# apply special number format
1377 0 : if( nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND )
1378 : {
1379 0 : ScPatternAttr aPattern( GetDoc().GetPool() );
1380 0 : GetNumFmtBuffer().FillScFmtToItemSet( aPattern.GetItemSet(), nForceScNumFmt );
1381 0 : rDoc.ApplyPatternAreaTab( nScCol1, nScRow1, nScCol2, nScRow2, nScTab, aPattern );
1382 : }
1383 0 : }
1384 :
1385 0 : /*static*/ void XclImpXF::ApplyPatternForBiff2CellFormat( const XclImpRoot& rRoot,
1386 : const ScAddress& rScPos, sal_uInt8 nFlags1, sal_uInt8 nFlags2, sal_uInt8 nFlags3 )
1387 : {
1388 : /* Create an XF object and let it do the work. We will have access to its
1389 : private members here. */
1390 0 : XclImpXF aXF( rRoot );
1391 :
1392 : // no used flags available in BIFF2 (always true)
1393 0 : aXF.SetAllUsedFlags( true );
1394 :
1395 : // set the attributes
1396 0 : aXF.maProtection.FillFromXF2( nFlags1 );
1397 0 : aXF.maAlignment.FillFromXF2( nFlags3 );
1398 0 : aXF.maBorder.FillFromXF2( nFlags3 );
1399 0 : aXF.maArea.FillFromXF2( nFlags3 );
1400 0 : aXF.mnXclNumFmt = ::extract_value< sal_uInt16 >( nFlags2, 0, 6 );
1401 0 : aXF.mnXclFont = ::extract_value< sal_uInt16 >( nFlags2, 6, 2 );
1402 :
1403 : // write the attributes to the cell
1404 0 : aXF.ApplyPattern( rScPos.Col(), rScPos.Row(), rScPos.Col(), rScPos.Row(), rScPos.Tab() );
1405 0 : }
1406 :
1407 7020 : void XclImpXF::SetUsedFlags( sal_uInt8 nUsedFlags )
1408 : {
1409 : /* Notes about finding the mb***Used flags:
1410 : - In cell XFs a *set* bit means a used attribute.
1411 : - In style XFs a *cleared* bit means a used attribute.
1412 : The mb***Used members always store true, if the attribute is used.
1413 : The "mbCellXF == ::get_flag(...)" construct evaluates to true in
1414 : both mentioned cases: cell XF and set bit; or style XF and cleared bit.
1415 : */
1416 7020 : mbProtUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_PROT ));
1417 7020 : mbFontUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_FONT ));
1418 7020 : mbFmtUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_VALFMT ));
1419 7020 : mbAlignUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_ALIGN ));
1420 7020 : mbBorderUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_BORDER ));
1421 7020 : mbAreaUsed = (mbCellXF == ::get_flag( nUsedFlags, EXC_XF_DIFF_AREA ));
1422 7020 : }
1423 :
1424 2410 : XclImpStyle::XclImpStyle( const XclImpRoot& rRoot ) :
1425 : XclImpRoot( rRoot ),
1426 : mnXfId( EXC_XF_NOTFOUND ),
1427 : mnBuiltinId( EXC_STYLE_USERDEF ),
1428 : mnLevel( EXC_STYLE_NOLEVEL ),
1429 : mbBuiltin( false ),
1430 : mbCustom( false ),
1431 : mbHidden( false ),
1432 2410 : mpStyleSheet( 0 )
1433 : {
1434 2410 : }
1435 :
1436 2410 : void XclImpStyle::ReadStyle( XclImpStream& rStrm )
1437 : {
1438 : OSL_ENSURE_BIFF( GetBiff() >= EXC_BIFF3 );
1439 :
1440 : sal_uInt16 nXFIndex;
1441 2410 : rStrm >> nXFIndex;
1442 2410 : mnXfId = nXFIndex & EXC_STYLE_XFMASK;
1443 2410 : mbBuiltin = ::get_flag( nXFIndex, EXC_STYLE_BUILTIN );
1444 :
1445 2410 : if( mbBuiltin )
1446 : {
1447 924 : rStrm >> mnBuiltinId >> mnLevel;
1448 : }
1449 : else
1450 : {
1451 1486 : maName = (GetBiff() <= EXC_BIFF5) ? rStrm.ReadByteString( false ) : rStrm.ReadUniString();
1452 : // #i103281# check if this is a new built-in style introduced in XL2007
1453 1486 : if( (GetBiff() == EXC_BIFF8) && (rStrm.GetNextRecId() == EXC_ID_STYLEEXT) && rStrm.StartNextRecord() )
1454 : {
1455 : sal_uInt8 nExtFlags;
1456 660 : rStrm.Ignore( 12 );
1457 660 : rStrm >> nExtFlags;
1458 660 : mbBuiltin = ::get_flag( nExtFlags, EXC_STYLEEXT_BUILTIN );
1459 660 : mbCustom = ::get_flag( nExtFlags, EXC_STYLEEXT_CUSTOM );
1460 660 : mbHidden = ::get_flag( nExtFlags, EXC_STYLEEXT_HIDDEN );
1461 660 : if( mbBuiltin )
1462 : {
1463 656 : rStrm.Ignore( 1 ); // category
1464 656 : rStrm >> mnBuiltinId >> mnLevel;
1465 : }
1466 : }
1467 : }
1468 2410 : }
1469 :
1470 3488 : ScStyleSheet* XclImpStyle::CreateStyleSheet()
1471 : {
1472 : // #i1624# #i1768# ignore unnamed user styles
1473 3488 : if( !mpStyleSheet && (!maFinalName.isEmpty()) )
1474 : {
1475 974 : bool bCreatePattern = false;
1476 974 : XclImpXF* pXF = GetXFBuffer().GetXF( mnXfId );
1477 :
1478 974 : bool bDefStyle = mbBuiltin && (mnBuiltinId == EXC_STYLE_NORMAL);
1479 974 : if( bDefStyle )
1480 : {
1481 : // set all flags to true to get all items in XclImpXF::CreatePattern()
1482 124 : if( pXF ) pXF->SetAllUsedFlags( true );
1483 : // use existing "Default" style sheet
1484 124 : mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find(
1485 124 : ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) );
1486 : OSL_ENSURE( mpStyleSheet, "XclImpStyle::CreateStyleSheet - Default style not found" );
1487 124 : bCreatePattern = true;
1488 : }
1489 : else
1490 : {
1491 : /* #i103281# do not create another style sheet of the same name,
1492 : if it exists already. This is needed to prevent that styles
1493 : pasted from clipboard get duplicated over and over. */
1494 850 : mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find( maFinalName, SFX_STYLE_FAMILY_PARA ) );
1495 850 : if( !mpStyleSheet )
1496 : {
1497 850 : mpStyleSheet = &static_cast< ScStyleSheet& >( GetStyleSheetPool().Make( maFinalName, SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_USERDEF ) );
1498 850 : bCreatePattern = true;
1499 : }
1500 : }
1501 :
1502 : // bDefStyle==true omits default pool items in CreatePattern()
1503 974 : if( bCreatePattern && mpStyleSheet && pXF )
1504 974 : mpStyleSheet->GetItemSet().Put( pXF->CreatePattern( bDefStyle ).GetItemSet() );
1505 : }
1506 3488 : return mpStyleSheet;
1507 : }
1508 :
1509 2410 : void XclImpStyle::CreateUserStyle( const OUString& rFinalName )
1510 : {
1511 2410 : maFinalName = rFinalName;
1512 2410 : if( !IsBuiltin() || mbCustom )
1513 830 : CreateStyleSheet();
1514 2410 : }
1515 :
1516 144 : XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot& rRoot ) :
1517 144 : XclImpRoot( rRoot )
1518 : {
1519 144 : }
1520 :
1521 0 : void XclImpXFBuffer::Initialize()
1522 : {
1523 0 : maXFList.clear();
1524 0 : maBuiltinStyles.clear();
1525 0 : maUserStyles.clear();
1526 0 : maStylesByXf.clear();
1527 0 : }
1528 :
1529 7020 : void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
1530 : {
1531 7020 : XclImpXF* pXF = new XclImpXF( GetRoot() );
1532 7020 : pXF->ReadXF( rStrm );
1533 7020 : maXFList.push_back( pXF );
1534 7020 : }
1535 :
1536 2410 : void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
1537 : {
1538 2410 : XclImpStyle* pStyle = new XclImpStyle( GetRoot() );
1539 2410 : pStyle->ReadStyle( rStrm );
1540 2410 : (pStyle->IsBuiltin() ? maBuiltinStyles : maUserStyles).push_back( pStyle );
1541 : OSL_ENSURE( maStylesByXf.count( pStyle->GetXfId() ) == 0, "XclImpXFBuffer::ReadStyle - multiple styles with equal XF identifier" );
1542 2410 : maStylesByXf[ pStyle->GetXfId() ] = pStyle;
1543 2410 : }
1544 :
1545 24826 : sal_uInt16 XclImpXFBuffer::GetFontIndex( sal_uInt16 nXFIndex ) const
1546 : {
1547 24826 : const XclImpXF* pXF = GetXF( nXFIndex );
1548 24826 : return pXF ? pXF->GetFontIndex() : EXC_FONT_NOTFOUND;
1549 : }
1550 :
1551 24826 : const XclImpFont* XclImpXFBuffer::GetFont( sal_uInt16 nXFIndex ) const
1552 : {
1553 24826 : return GetFontBuffer().GetFont( GetFontIndex( nXFIndex ) );
1554 : }
1555 :
1556 : namespace {
1557 :
1558 : /** Functor for case-insensitive string comparison, usable in maps etc. */
1559 : struct IgnoreCaseCompare
1560 : {
1561 39760 : inline bool operator()( const OUString& rName1, const OUString& rName2 ) const
1562 39760 : { return rName1.compareToIgnoreAsciiCase( rName2 ) < 0; }
1563 : };
1564 :
1565 : } // namespace
1566 :
1567 142 : void XclImpXFBuffer::CreateUserStyles()
1568 : {
1569 : // calculate final names of all styles
1570 : typedef ::std::map< OUString, XclImpStyle*, IgnoreCaseCompare > CellStyleNameMap;
1571 : typedef ::std::vector< XclImpStyle* > XclImpStyleVector;
1572 :
1573 142 : CellStyleNameMap aCellStyles;
1574 284 : XclImpStyleVector aConflictNameStyles;
1575 :
1576 : /* First, reserve style names that are built-in in Calc. This causes that
1577 : imported cell styles get different unused names and thus do not try to
1578 : overwrite these built-in styles. For BIFF4 workbooks (which contain a
1579 : separate list of cell styles per sheet), reserve all existing styles if
1580 : current sheet is not the first sheet (this styles buffer will be
1581 : initialized again for every new sheet). This will create unique names
1582 : for styles in different sheets with the same name. Assuming that the
1583 : BIFF4W import filter is never used to import from clipboard... */
1584 142 : bool bReserveAll = (GetBiff() == EXC_BIFF4) && (GetCurrScTab() > 0);
1585 284 : SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
1586 284 : OUString aStandardName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
1587 852 : for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
1588 710 : if( (pStyleSheet->GetName() != aStandardName) && (bReserveAll || !pStyleSheet->IsUserDefined()) )
1589 568 : if( aCellStyles.count( pStyleSheet->GetName() ) == 0 )
1590 568 : aCellStyles[ pStyleSheet->GetName() ] = 0;
1591 :
1592 : /* Calculate names of built-in styles. Store styles with reserved names
1593 : in the aConflictNameStyles list. */
1594 1722 : for( XclImpStyleList::iterator itStyle = maBuiltinStyles.begin(); itStyle != maBuiltinStyles.end(); ++itStyle )
1595 : {
1596 1580 : OUString aStyleName = XclTools::GetBuiltInStyleName( itStyle->GetBuiltinId(), itStyle->GetName(), itStyle->GetLevel() );
1597 : OSL_ENSURE( bReserveAll || (aCellStyles.count( aStyleName ) == 0),
1598 : "XclImpXFBuffer::CreateUserStyles - multiple styles with equal built-in identifier" );
1599 1580 : if( aCellStyles.count( aStyleName ) > 0 )
1600 0 : aConflictNameStyles.push_back( &(*itStyle) );
1601 : else
1602 1580 : aCellStyles[ aStyleName ] = &(*itStyle);
1603 1580 : }
1604 :
1605 : /* Calculate names of user defined styles. Store styles with reserved
1606 : names in the aConflictNameStyles list. */
1607 972 : for( XclImpStyleList::iterator itStyle = maUserStyles.begin(); itStyle != maUserStyles.end(); ++itStyle )
1608 : {
1609 : // #i1624# #i1768# ignore unnamed user styles
1610 830 : if( !itStyle->GetName().isEmpty() )
1611 : {
1612 830 : if( aCellStyles.count( itStyle->GetName() ) > 0 )
1613 0 : aConflictNameStyles.push_back( &(*itStyle) );
1614 : else
1615 830 : aCellStyles[ itStyle->GetName() ] = &(*itStyle);
1616 : }
1617 : }
1618 :
1619 : // find unused names for all styles with conflicting names
1620 142 : for( XclImpStyleVector::iterator aIt = aConflictNameStyles.begin(), aEnd = aConflictNameStyles.end(); aIt != aEnd; ++aIt )
1621 : {
1622 0 : XclImpStyle* pStyle = *aIt;
1623 0 : OUString aUnusedName;
1624 0 : sal_Int32 nIndex = 0;
1625 0 : do
1626 : {
1627 0 : aUnusedName = pStyle->GetName() + " " + OUString::number( ++nIndex );
1628 : }
1629 0 : while( aCellStyles.count( aUnusedName ) > 0 );
1630 0 : aCellStyles[ aUnusedName ] = pStyle;
1631 0 : }
1632 :
1633 : // set final names and create user-defined and modified built-in cell styles
1634 3120 : for( CellStyleNameMap::iterator aIt = aCellStyles.begin(), aEnd = aCellStyles.end(); aIt != aEnd; ++aIt )
1635 2978 : if( aIt->second )
1636 2552 : aIt->second->CreateUserStyle( aIt->first );
1637 142 : }
1638 :
1639 2658 : ScStyleSheet* XclImpXFBuffer::CreateStyleSheet( sal_uInt16 nXFIndex )
1640 : {
1641 2658 : XclImpStyleMap::iterator aIt = maStylesByXf.find( nXFIndex );
1642 2658 : return (aIt == maStylesByXf.end()) ? 0 : aIt->second->CreateStyleSheet();
1643 : }
1644 :
1645 : // Buffer for XF indexes in cells =============================================
1646 :
1647 16 : IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange )
1648 :
1649 1192142 : bool XclImpXFRange::Expand( SCROW nScRow, const XclImpXFIndex& rXFIndex )
1650 : {
1651 1192142 : if( maXFIndex != rXFIndex )
1652 135616 : return false;
1653 :
1654 1056526 : if( mnScRow2 + 1 == nScRow )
1655 : {
1656 1044022 : ++mnScRow2;
1657 1044022 : return true;
1658 : }
1659 12504 : if( mnScRow1 > 0 && (mnScRow1 - 1 == nScRow) )
1660 : {
1661 0 : --mnScRow1;
1662 0 : return true;
1663 : }
1664 :
1665 12504 : return false;
1666 : }
1667 :
1668 4952 : bool XclImpXFRange::Expand( const XclImpXFRange& rNextRange )
1669 : {
1670 : OSL_ENSURE( mnScRow2 < rNextRange.mnScRow1, "XclImpXFRange::Expand - rows out of order" );
1671 4952 : if( (maXFIndex == rNextRange.maXFIndex) && (mnScRow2 + 1 == rNextRange.mnScRow1) )
1672 : {
1673 1198 : mnScRow2 = rNextRange.mnScRow2;
1674 1198 : return true;
1675 : }
1676 3754 : return false;
1677 : }
1678 :
1679 30722 : void XclImpXFRangeColumn::SetDefaultXF( const XclImpXFIndex& rXFIndex )
1680 : {
1681 : // List should be empty when inserting the default column format.
1682 : // Later explicit SetXF() calls will break up this range.
1683 : OSL_ENSURE( maIndexList.empty(), "XclImpXFRangeColumn::SetDefaultXF - Setting Default Column XF is not empty" );
1684 :
1685 : // insert a complete row range with one insert.
1686 30722 : maIndexList.push_back( new XclImpXFRange( 0, MAXROW, rXFIndex ) );
1687 30722 : }
1688 :
1689 1249486 : void XclImpXFRangeColumn::SetXF( SCROW nScRow, const XclImpXFIndex& rXFIndex )
1690 : {
1691 : XclImpXFRange* pPrevRange;
1692 : XclImpXFRange* pNextRange;
1693 : sal_uLong nNextIndex;
1694 :
1695 1249486 : Find( pPrevRange, pNextRange, nNextIndex, nScRow );
1696 :
1697 : // previous range:
1698 : // try to overwrite XF (if row is contained in) or try to expand range
1699 1249486 : if( pPrevRange )
1700 : {
1701 1217270 : if( pPrevRange->Contains( nScRow ) ) // overwrite old XF
1702 : {
1703 658230 : if( rXFIndex == pPrevRange->maXFIndex )
1704 1118390 : return;
1705 :
1706 650646 : SCROW nFirstScRow = pPrevRange->mnScRow1;
1707 650646 : SCROW nLastScRow = pPrevRange->mnScRow2;
1708 650646 : sal_uLong nIndex = nNextIndex - 1;
1709 650646 : XclImpXFRange* pThisRange = pPrevRange;
1710 650646 : pPrevRange = (nIndex > 0 && nIndex <= maIndexList.size()) ? &(maIndexList[ nIndex - 1 ]) : 0;
1711 :
1712 650646 : if( nFirstScRow == nLastScRow ) // replace solely XF
1713 : {
1714 2264 : pThisRange->maXFIndex = rXFIndex;
1715 2264 : TryConcatPrev( nNextIndex ); // try to concat. next with this
1716 2264 : TryConcatPrev( nIndex ); // try to concat. this with previous
1717 : }
1718 648382 : else if( nFirstScRow == nScRow ) // replace first XF
1719 : {
1720 635258 : ++(pThisRange->mnScRow1);
1721 : // try to concatenate with previous of this
1722 635258 : if( !pPrevRange || !pPrevRange->Expand( nScRow, rXFIndex ) )
1723 43812 : Insert( new XclImpXFRange( nScRow, rXFIndex ), nIndex );
1724 : }
1725 13124 : else if( nLastScRow == nScRow ) // replace last XF
1726 : {
1727 0 : --(pThisRange->mnScRow2);
1728 0 : if( !pNextRange || !pNextRange->Expand( nScRow, rXFIndex ) )
1729 0 : Insert( new XclImpXFRange( nScRow, rXFIndex ), nNextIndex );
1730 : }
1731 : else // insert in the middle of the range
1732 : {
1733 13124 : pThisRange->mnScRow1 = nScRow + 1;
1734 : // List::Insert() moves entries towards end of list, so insert twice at nIndex
1735 13124 : Insert( new XclImpXFRange( nScRow, rXFIndex ), nIndex );
1736 13124 : Insert( new XclImpXFRange( nFirstScRow, nScRow - 1, pThisRange->maXFIndex ), nIndex );
1737 : }
1738 650646 : return;
1739 : }
1740 559040 : else if( pPrevRange->Expand( nScRow, rXFIndex ) ) // try to expand
1741 : {
1742 452576 : TryConcatPrev( nNextIndex ); // try to concatenate next with expanded
1743 452576 : return;
1744 : }
1745 : }
1746 :
1747 : // try to expand next range
1748 138680 : if( pNextRange && pNextRange->Expand( nScRow, rXFIndex ) )
1749 0 : return;
1750 :
1751 : // create new range
1752 138680 : Insert( new XclImpXFRange( nScRow, rXFIndex ), nNextIndex );
1753 : }
1754 :
1755 208740 : void XclImpXFRangeColumn::Insert(XclImpXFRange* pXFRange, sal_uLong nIndex)
1756 : {
1757 208740 : maIndexList.insert( maIndexList.begin() + nIndex, pXFRange );
1758 208740 : }
1759 :
1760 1249486 : void XclImpXFRangeColumn::Find(
1761 : XclImpXFRange*& rpPrevRange, XclImpXFRange*& rpNextRange,
1762 : sal_uLong& rnNextIndex, SCROW nScRow )
1763 : {
1764 :
1765 : // test whether list is empty
1766 1249486 : if( maIndexList.empty() )
1767 : {
1768 32136 : rpPrevRange = rpNextRange = 0;
1769 32136 : rnNextIndex = 0;
1770 32136 : return;
1771 : }
1772 :
1773 1217350 : rpPrevRange = &maIndexList.front();
1774 1217350 : rpNextRange = &maIndexList.back();
1775 :
1776 : // test whether row is at end of list (contained in or behind last range)
1777 : // rpPrevRange will contain a possible existing row
1778 1217350 : if( rpNextRange->mnScRow1 <= nScRow )
1779 : {
1780 1194914 : rpPrevRange = rpNextRange;
1781 1194914 : rpNextRange = 0;
1782 1194914 : rnNextIndex = maIndexList.size();
1783 1194914 : return;
1784 : }
1785 :
1786 : // test whether row is at beginning of list (really before first range)
1787 22436 : if( nScRow < rpPrevRange->mnScRow1 )
1788 : {
1789 80 : rpNextRange = rpPrevRange;
1790 80 : rpPrevRange = 0;
1791 80 : rnNextIndex = 0;
1792 80 : return;
1793 : }
1794 :
1795 : // loop: find range entries before and after new row
1796 : // break the loop if there is no more range between first and last -or-
1797 : // if rpPrevRange contains nScRow (rpNextRange will never contain nScRow)
1798 22356 : sal_uLong nPrevIndex = 0;
1799 : sal_uLong nMidIndex;
1800 22356 : rnNextIndex = maIndexList.size() - 1;
1801 : XclImpXFRange* pMidRange;
1802 117312 : while( ((rnNextIndex - nPrevIndex) > 1) && (rpPrevRange->mnScRow2 < nScRow) )
1803 : {
1804 72600 : nMidIndex = (nPrevIndex + rnNextIndex) / 2;
1805 72600 : pMidRange = &maIndexList[nMidIndex];
1806 : OSL_ENSURE( pMidRange, "XclImpXFRangeColumn::Find - missing XF index range" );
1807 72600 : if( nScRow < pMidRange->mnScRow1 ) // row is really before pMidRange
1808 : {
1809 11142 : rpNextRange = pMidRange;
1810 11142 : rnNextIndex = nMidIndex;
1811 : }
1812 : else // row is in or after pMidRange
1813 : {
1814 61458 : rpPrevRange = pMidRange;
1815 61458 : nPrevIndex = nMidIndex;
1816 : }
1817 : }
1818 :
1819 : // find next rpNextRange if rpPrevRange contains nScRow
1820 22356 : if( nScRow <= rpPrevRange->mnScRow2 )
1821 : {
1822 19626 : rnNextIndex = nPrevIndex + 1;
1823 19626 : rpNextRange = &maIndexList[rnNextIndex];
1824 : }
1825 : }
1826 :
1827 457104 : void XclImpXFRangeColumn::TryConcatPrev( sal_uLong nIndex )
1828 : {
1829 457104 : if( !nIndex || nIndex >= maIndexList.size() )
1830 909256 : return;
1831 :
1832 4952 : XclImpXFRange& prevRange = maIndexList[ nIndex - 1 ];
1833 4952 : XclImpXFRange& nextRange = maIndexList[ nIndex ];
1834 :
1835 4952 : if( prevRange.Expand( nextRange ) )
1836 1198 : maIndexList.erase( maIndexList.begin() + nIndex );
1837 : }
1838 :
1839 144 : XclImpXFRangeBuffer::XclImpXFRangeBuffer( const XclImpRoot& rRoot ) :
1840 144 : XclImpRoot( rRoot )
1841 : {
1842 144 : }
1843 :
1844 288 : XclImpXFRangeBuffer::~XclImpXFRangeBuffer()
1845 : {
1846 288 : }
1847 :
1848 416 : void XclImpXFRangeBuffer::Initialize()
1849 : {
1850 416 : maColumns.clear();
1851 416 : maHyperlinks.clear();
1852 416 : maMergeList.RemoveAll();
1853 416 : }
1854 :
1855 1249486 : void XclImpXFRangeBuffer::SetXF( const ScAddress& rScPos, sal_uInt16 nXFIndex, XclImpXFInsertMode eMode )
1856 : {
1857 1249486 : SCCOL nScCol = rScPos.Col();
1858 1249486 : SCROW nScRow = rScPos.Row();
1859 :
1860 : // set cell XF's
1861 1249486 : size_t nIndex = static_cast< size_t >( nScCol );
1862 1249486 : if( maColumns.size() <= nIndex )
1863 31854 : maColumns.resize( nIndex + 1 );
1864 1249486 : if( !maColumns[ nIndex ] )
1865 32136 : maColumns[ nIndex ].reset( new XclImpXFRangeColumn );
1866 : // remember all Boolean cells, they will get 'Standard' number format
1867 1249486 : maColumns[ nIndex ]->SetXF( nScRow, XclImpXFIndex( nXFIndex, eMode == xlXFModeBoolCell ) );
1868 :
1869 : // set "center across selection" and "fill" attribute for all following empty cells
1870 : // ignore it on row default XFs
1871 1249486 : if( eMode != xlXFModeRow )
1872 : {
1873 526542 : const XclImpXF* pXF = GetXFBuffer().GetXF( nXFIndex );
1874 526542 : if( pXF && ((pXF->GetHorAlign() == EXC_XF_HOR_CENTER_AS) || (pXF->GetHorAlign() == EXC_XF_HOR_FILL)) )
1875 : {
1876 : // expand last merged range if this attribute is set repeatedly
1877 0 : ScRange* pRange = maMergeList.empty() ? NULL : maMergeList.back();
1878 0 : if (pRange && (pRange->aEnd.Row() == nScRow) && (pRange->aEnd.Col() + 1 == nScCol) && (eMode == xlXFModeBlank))
1879 0 : pRange->aEnd.IncCol();
1880 0 : else if( eMode != xlXFModeBlank ) // do not merge empty cells
1881 0 : SetMerge( nScCol, nScRow );
1882 : }
1883 : }
1884 1249486 : }
1885 :
1886 63660 : void XclImpXFRangeBuffer::SetXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1887 : {
1888 63660 : SetXF( rScPos, nXFIndex, xlXFModeCell );
1889 63660 : }
1890 :
1891 462880 : void XclImpXFRangeBuffer::SetBlankXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1892 : {
1893 462880 : SetXF( rScPos, nXFIndex, xlXFModeBlank );
1894 462880 : }
1895 :
1896 2 : void XclImpXFRangeBuffer::SetBoolXF( const ScAddress& rScPos, sal_uInt16 nXFIndex )
1897 : {
1898 2 : SetXF( rScPos, nXFIndex, xlXFModeBoolCell );
1899 2 : }
1900 :
1901 706 : void XclImpXFRangeBuffer::SetRowDefXF( SCROW nScRow, sal_uInt16 nXFIndex )
1902 : {
1903 723650 : for( SCCOL nScCol = 0; nScCol <= MAXCOL; ++nScCol )
1904 722944 : SetXF( ScAddress( nScCol, nScRow, 0 ), nXFIndex, xlXFModeRow );
1905 706 : }
1906 :
1907 30722 : void XclImpXFRangeBuffer::SetColumnDefXF( SCCOL nScCol, sal_uInt16 nXFIndex )
1908 : {
1909 : // our array should not have values when creating the default column format.
1910 30722 : size_t nIndex = static_cast< size_t >( nScCol );
1911 30722 : if( maColumns.size() <= nIndex )
1912 30722 : maColumns.resize( nIndex + 1 );
1913 : OSL_ENSURE( !maColumns[ nIndex ], "XclImpXFRangeBuffer::SetColumnDefXF - default column of XFs already has values" );
1914 30722 : maColumns[ nIndex ].reset( new XclImpXFRangeColumn );
1915 30722 : maColumns[ nIndex ]->SetDefaultXF( XclImpXFIndex( nXFIndex ) );
1916 30722 : }
1917 :
1918 1434 : void XclImpXFRangeBuffer::SetBorderLine( const ScRange& rRange, SCTAB nScTab, sal_uInt16 nLine )
1919 : {
1920 1434 : SCCOL nFromScCol = (nLine == BOX_LINE_RIGHT) ? rRange.aEnd.Col() : rRange.aStart.Col();
1921 1434 : SCROW nFromScRow = (nLine == BOX_LINE_BOTTOM) ? rRange.aEnd.Row() : rRange.aStart.Row();
1922 1434 : ScDocument& rDoc = GetDoc();
1923 :
1924 : const SvxBoxItem* pFromItem = static_cast< const SvxBoxItem* >(
1925 1434 : rDoc.GetAttr( nFromScCol, nFromScRow, nScTab, ATTR_BORDER ) );
1926 : const SvxBoxItem* pToItem = static_cast< const SvxBoxItem* >(
1927 1434 : rDoc.GetAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, ATTR_BORDER ) );
1928 :
1929 1434 : SvxBoxItem aNewItem( *pToItem );
1930 1434 : aNewItem.SetLine( pFromItem->GetLine( nLine ), nLine );
1931 1434 : rDoc.ApplyAttr( rRange.aStart.Col(), rRange.aStart.Row(), nScTab, aNewItem );
1932 1434 : }
1933 :
1934 16 : void XclImpXFRangeBuffer::SetHyperlink( const XclRange& rXclRange, const OUString& rUrl )
1935 : {
1936 16 : maHyperlinks.push_back( XclImpHyperlinkRange( rXclRange, rUrl ) );
1937 16 : }
1938 :
1939 0 : void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol, SCROW nScRow )
1940 : {
1941 0 : maMergeList.Append( ScRange( nScCol, nScRow, 0 ) );
1942 0 : }
1943 :
1944 1424 : void XclImpXFRangeBuffer::SetMerge( SCCOL nScCol1, SCROW nScRow1, SCCOL nScCol2, SCROW nScRow2 )
1945 : {
1946 1424 : if( (nScCol1 < nScCol2) || (nScRow1 < nScRow2) )
1947 1424 : maMergeList.Append( ScRange( nScCol1, nScRow1, 0, nScCol2, nScRow2, 0 ) );
1948 1424 : }
1949 :
1950 416 : void XclImpXFRangeBuffer::Finalize()
1951 : {
1952 416 : ScDocumentImport& rDoc = GetDocImport();
1953 416 : SCTAB nScTab = GetCurrScTab();
1954 :
1955 : // apply patterns
1956 416 : XclImpXFBuffer& rXFBuffer = GetXFBuffer();
1957 63688 : for( XclImpXFRangeColumnVec::const_iterator aVBeg = maColumns.begin(), aVEnd = maColumns.end(), aVIt = aVBeg; aVIt != aVEnd; ++aVIt )
1958 : {
1959 : // apply all cell styles of an existing column
1960 63272 : if( aVIt->get() )
1961 : {
1962 62858 : XclImpXFRangeColumn& rColumn = **aVIt;
1963 62858 : SCCOL nScCol = static_cast< SCCOL >( aVIt - aVBeg );
1964 62858 : list<ScAttrEntry> aAttrs;
1965 :
1966 301122 : for (XclImpXFRangeColumn::IndexList::iterator itr = rColumn.begin(), itrEnd = rColumn.end();
1967 : itr != itrEnd; ++itr)
1968 : {
1969 238264 : XclImpXFRange& rStyle = *itr;
1970 238264 : const XclImpXFIndex& rXFIndex = rStyle.maXFIndex;
1971 238264 : XclImpXF* pXF = rXFBuffer.GetXF( rXFIndex.GetXFIndex() );
1972 238264 : if (!pXF)
1973 1114 : continue;
1974 :
1975 237150 : sal_uInt32 nForceScNumFmt = rXFIndex.IsBoolCell() ?
1976 237150 : GetNumFmtBuffer().GetStdScNumFmt() : NUMBERFORMAT_ENTRY_NOT_FOUND;
1977 :
1978 237150 : pXF->ApplyPatternToAttrList(aAttrs, rStyle.mnScRow1, rStyle.mnScRow2, nForceScNumFmt);
1979 : }
1980 :
1981 62858 : if (aAttrs.empty() || aAttrs.back().nRow != MAXROW)
1982 : {
1983 : ScAttrEntry aEntry;
1984 32136 : aEntry.nRow = MAXROW;
1985 32136 : aEntry.pPattern = rDoc.getDoc().GetDefPattern();
1986 32136 : aAttrs.push_back(aEntry);
1987 : }
1988 :
1989 62858 : ScDocumentImport::Attrs aAttrParam;
1990 62858 : aAttrParam.mnSize = aAttrs.size();
1991 : assert(aAttrParam.mnSize > 0);
1992 62858 : aAttrParam.mpData = new ScAttrEntry[aAttrParam.mnSize];
1993 62858 : aAttrParam.mbLatinNumFmtOnly = false; // when unsure, set it to false.
1994 62858 : list<ScAttrEntry>::const_iterator itr = aAttrs.begin(), itrEnd = aAttrs.end();
1995 382638 : for (size_t i = 0; itr != itrEnd; ++itr, ++i)
1996 319780 : aAttrParam.mpData[i] = *itr;
1997 :
1998 62858 : rDoc.setAttrEntries(nScTab, nScCol, aAttrParam);
1999 : }
2000 : }
2001 :
2002 : // insert hyperlink cells
2003 432 : for( XclImpHyperlinkList::const_iterator aLIt = maHyperlinks.begin(), aLEnd = maHyperlinks.end(); aLIt != aLEnd; ++aLIt )
2004 16 : XclImpHyperlink::InsertUrl( GetRoot(), aLIt->first, aLIt->second );
2005 :
2006 : // apply cell merging
2007 1840 : for ( size_t i = 0, nRange = maMergeList.size(); i < nRange; ++i )
2008 : {
2009 1424 : const ScRange* pRange = maMergeList[ i ];
2010 1424 : const ScAddress& rStart = pRange->aStart;
2011 1424 : const ScAddress& rEnd = pRange->aEnd;
2012 1424 : bool bMultiCol = rStart.Col() != rEnd.Col();
2013 1424 : bool bMultiRow = rStart.Row() != rEnd.Row();
2014 : // set correct right border
2015 1424 : if( bMultiCol )
2016 1412 : SetBorderLine( *pRange, nScTab, BOX_LINE_RIGHT );
2017 : // set correct lower border
2018 1424 : if( bMultiRow )
2019 22 : SetBorderLine( *pRange, nScTab, BOX_LINE_BOTTOM );
2020 : // do merge
2021 1424 : if( bMultiCol || bMultiRow )
2022 1424 : rDoc.getDoc().DoMerge( nScTab, rStart.Col(), rStart.Row(), rEnd.Col(), rEnd.Row() );
2023 : // #i93609# merged range in a single row: test if manual row height is needed
2024 1424 : if( !bMultiRow )
2025 : {
2026 1402 : bool bTextWrap = static_cast<const SfxBoolItem*>( rDoc.getDoc().GetAttr( rStart.Col(), rStart.Row(), rStart.Tab(), ATTR_LINEBREAK ) )->GetValue();
2027 1402 : if( !bTextWrap && (rDoc.getDoc().GetCellType( rStart ) == CELLTYPE_EDIT) )
2028 0 : if (const EditTextObject* pEditObj = rDoc.getDoc().GetEditText(rStart))
2029 0 : bTextWrap = pEditObj->GetParagraphCount() > 1;
2030 1402 : if( bTextWrap )
2031 10 : GetOldRoot().pColRowBuff->SetManualRowHeight( rStart.Row() );
2032 : }
2033 : }
2034 464 : }
2035 :
2036 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|