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