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