xref: /trunk/main/sc/source/filter/excel/xistyle.cxx (revision b77af630)
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_scfilt.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 &,const SfxHint &)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 ()__anonb8c81efb0211::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