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