xref: /trunk/main/sc/source/filter/excel/xltools.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 
27 #include <algorithm>
28 #include <math.h>
29 #include <sal/mathconf.h>
30 #include <unotools/fontcvt.hxx>
31 #include <sfx2/objsh.hxx>
32 #include <editeng/editstat.hxx>
33 #include <filter/msfilter/msvbahelper.hxx>
34 #include "xestream.hxx"
35 #include "document.hxx"
36 #include "docuno.hxx"
37 #include "editutil.hxx"
38 #include "formula/errorcodes.hxx"
39 #include "globstr.hrc"
40 #include "xlstyle.hxx"
41 #include "xlname.hxx"
42 #include "xistream.hxx"
43 #include "xiroot.hxx"
44 #include "xltools.hxx"
45 
46 using ::rtl::OUString;
47 
48 // GUID import/export =========================================================
49 
XclGuid()50 XclGuid::XclGuid()
51 {
52     ::std::fill( mpnData, STATIC_ARRAY_END( mpnData ), 0 );
53 }
54 
XclGuid(sal_uInt32 nData1,sal_uInt16 nData2,sal_uInt16 nData3,sal_uInt8 nData41,sal_uInt8 nData42,sal_uInt8 nData43,sal_uInt8 nData44,sal_uInt8 nData45,sal_uInt8 nData46,sal_uInt8 nData47,sal_uInt8 nData48)55 XclGuid::XclGuid(
56         sal_uInt32 nData1, sal_uInt16 nData2, sal_uInt16 nData3,
57         sal_uInt8 nData41, sal_uInt8 nData42, sal_uInt8 nData43, sal_uInt8 nData44,
58         sal_uInt8 nData45, sal_uInt8 nData46, sal_uInt8 nData47, sal_uInt8 nData48 )
59 {
60     // convert to little endian -> makes streaming easy
61     UInt32ToSVBT32( nData1, mpnData );
62     ShortToSVBT16( nData2, mpnData + 4 );
63     ShortToSVBT16( nData3, mpnData + 6 );
64     mpnData[  8 ] = nData41;
65     mpnData[  9 ] = nData42;
66     mpnData[ 10 ] = nData43;
67     mpnData[ 11 ] = nData44;
68     mpnData[ 12 ] = nData45;
69     mpnData[ 13 ] = nData46;
70     mpnData[ 14 ] = nData47;
71     mpnData[ 15 ] = nData48;
72 }
73 
operator ==(const XclGuid & rCmp1,const XclGuid & rCmp2)74 bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 )
75 {
76     return ::std::equal( rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ), rCmp2.mpnData );
77 }
78 
operator <(const XclGuid & rCmp1,const XclGuid & rCmp2)79 bool operator<( const XclGuid& rCmp1, const XclGuid& rCmp2 )
80 {
81     return ::std::lexicographical_compare(
82         rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ),
83         rCmp2.mpnData, STATIC_ARRAY_END( rCmp2.mpnData ) );
84 }
85 
operator >>(XclImpStream & rStrm,XclGuid & rGuid)86 XclImpStream& operator>>( XclImpStream& rStrm, XclGuid& rGuid )
87 {
88     rStrm.Read( rGuid.mpnData, 16 );     // mpnData always in little endian
89     return rStrm;
90 }
91 
operator <<(XclExpStream & rStrm,const XclGuid & rGuid)92 XclExpStream& operator<<( XclExpStream& rStrm, const XclGuid& rGuid )
93 {
94     rStrm.Write( rGuid.mpnData, 16 );    // mpnData already in little endian
95     return rStrm;
96 }
97 
98 // Excel Tools ================================================================
99 
100 // GUID's ---------------------------------------------------------------------
101 
102 const XclGuid XclTools::maGuidStdLink(
103     0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
104 
105 const XclGuid XclTools::maGuidUrlMoniker(
106     0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B );
107 
108 const XclGuid XclTools::maGuidFileMoniker(
109     0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 );
110 
111 // numeric conversion ---------------------------------------------------------
112 
GetDoubleFromRK(sal_Int32 nRKValue)113 double XclTools::GetDoubleFromRK( sal_Int32 nRKValue )
114 {
115     union
116     {
117         double fVal;
118         sal_math_Double smD;
119     };
120     fVal = 0.0;
121 
122     if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) )
123     {
124         sal_Int32 nTemp = nRKValue >> 2;
125         ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 );
126         fVal = nTemp;
127     }
128     else
129     {
130         smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK;
131     }
132 
133     if( ::get_flag( nRKValue, EXC_RK_100FLAG ) )
134         fVal /= 100.0;
135 
136     return fVal;
137 }
138 
GetRKFromDouble(sal_Int32 & rnRKValue,double fValue)139 bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue )
140 {
141     double fFrac, fInt;
142 
143     // integer
144     fFrac = modf( fValue, &fInt );
145     if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29
146     {
147         rnRKValue = static_cast< sal_Int32 >( fInt );
148         rnRKValue <<= 2;
149         rnRKValue |= EXC_RK_INT;
150         return true;
151     }
152 
153     // integer/100
154     fFrac = modf( fValue * 100.0, &fInt );
155     if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) )
156     {
157         rnRKValue = static_cast< sal_Int32 >( fInt );
158         rnRKValue <<= 2;
159         rnRKValue |= EXC_RK_INT100;
160         return true;
161     }
162 
163     // double
164     return false;
165 }
166 
GetScRotation(sal_uInt16 nXclRot,sal_Int32 nRotForStacked)167 sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked )
168 {
169     if( nXclRot == EXC_ROT_STACKED )
170         return nRotForStacked;
171     DBG_ASSERT( nXclRot <= 180, "XclTools::GetScRotation - illegal rotation angle" );
172     return static_cast< sal_Int32 >( (nXclRot <= 180) ? (100 * ((nXclRot > 90) ? (450 - nXclRot) : nXclRot)) : 0 );
173 }
174 
GetXclRotation(sal_Int32 nScRot)175 sal_uInt8 XclTools::GetXclRotation( sal_Int32 nScRot )
176 {
177     sal_Int32 nXclRot = nScRot / 100;
178     if( (0 <= nXclRot) && (nXclRot <= 90) )
179         return static_cast< sal_uInt8 >( nXclRot );
180     if( nXclRot < 180 )
181         return static_cast< sal_uInt8 >( 270 - nXclRot );
182     if( nXclRot < 270 )
183         return static_cast< sal_uInt8 >( nXclRot - 180 );
184     if( nXclRot < 360 )
185         return static_cast< sal_uInt8 >( 450 - nXclRot );
186     return 0;
187 }
188 
GetXclRotFromOrient(sal_uInt8 nXclOrient)189 sal_uInt8 XclTools::GetXclRotFromOrient( sal_uInt8 nXclOrient )
190 {
191     switch( nXclOrient )
192     {
193         case EXC_ORIENT_NONE:       return EXC_ROT_NONE;
194         case EXC_ORIENT_STACKED:    return EXC_ROT_STACKED;
195         case EXC_ORIENT_90CCW:      return EXC_ROT_90CCW;
196         case EXC_ORIENT_90CW:       return EXC_ROT_90CW;
197         default:    DBG_ERRORFILE( "XclTools::GetXclRotFromOrient - unknown text orientation" );
198     }
199     return EXC_ROT_NONE;
200 }
201 
GetXclOrientFromRot(sal_uInt16 nXclRot)202 sal_uInt8 XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot )
203 {
204     if( nXclRot == EXC_ROT_STACKED )
205         return EXC_ORIENT_STACKED;
206     DBG_ASSERT( nXclRot <= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" );
207     if( (45 < nXclRot) && (nXclRot <= 90) )
208         return EXC_ORIENT_90CCW;
209     if( (135 < nXclRot) && (nXclRot <= 180) )
210         return EXC_ORIENT_90CW;
211     return EXC_ORIENT_NONE;
212 }
213 
GetXclErrorCode(sal_uInt16 nScError)214 sal_uInt8 XclTools::GetXclErrorCode( sal_uInt16 nScError )
215 {
216     using namespace ScErrorCodes;
217     switch( nScError )
218     {
219         case errIllegalArgument:        return EXC_ERR_VALUE;
220         case errIllegalFPOperation:     return EXC_ERR_NUM;     // maybe DIV/0 or NUM...
221         case errDivisionByZero:         return EXC_ERR_DIV0;
222         case errIllegalParameter:       return EXC_ERR_VALUE;
223         case errPairExpected:           return EXC_ERR_VALUE;
224         case errOperatorExpected:       return EXC_ERR_VALUE;
225         case errVariableExpected:       return EXC_ERR_VALUE;
226         case errParameterExpected:      return EXC_ERR_VALUE;
227         case errNoValue:                return EXC_ERR_VALUE;
228         case errCircularReference:      return EXC_ERR_VALUE;
229         case errNoCode:                 return EXC_ERR_NULL;
230         case errNoRef:                  return EXC_ERR_REF;
231         case errNoName:                 return EXC_ERR_NAME;
232         case errNoAddin:                return EXC_ERR_NAME;
233         case errNoMacro:                return EXC_ERR_NAME;
234         case NOTAVAILABLE:              return EXC_ERR_NA;
235     }
236     return EXC_ERR_NA;
237 }
238 
GetScErrorCode(sal_uInt8 nXclError)239 sal_uInt16 XclTools::GetScErrorCode( sal_uInt8 nXclError )
240 {
241     using namespace ScErrorCodes;
242     switch( nXclError )
243     {
244         case EXC_ERR_NULL:  return errNoCode;
245         case EXC_ERR_DIV0:  return errDivisionByZero;
246         case EXC_ERR_VALUE: return errNoValue;
247         case EXC_ERR_REF:   return errNoRef;
248         case EXC_ERR_NAME:  return errNoName;
249         case EXC_ERR_NUM:   return errIllegalFPOperation;
250         case EXC_ERR_NA:    return NOTAVAILABLE;
251         default:            DBG_ERRORFILE( "XclTools::GetScErrorCode - unknown error code" );
252     }
253     return NOTAVAILABLE;
254 }
255 
ErrorToDouble(sal_uInt8 nXclError)256 double XclTools::ErrorToDouble( sal_uInt8 nXclError )
257 {
258     union
259     {
260         double fVal;
261         sal_math_Double smD;
262     };
263     ::rtl::math::setNan( &fVal );
264     smD.nan_parts.fraction_lo = GetScErrorCode( nXclError );
265     return fVal;
266 }
267 
ErrorToEnum(double & rfDblValue,sal_uInt8 bErrOrBool,sal_uInt8 nValue)268 XclBoolError XclTools::ErrorToEnum( double& rfDblValue, sal_uInt8 bErrOrBool, sal_uInt8 nValue )
269 {
270     XclBoolError eType;
271     if( bErrOrBool )
272     {
273         // error value
274         switch( nValue )
275         {
276             case EXC_ERR_NULL:  eType = xlErrNull;      break;
277             case EXC_ERR_DIV0:  eType = xlErrDiv0;      break;
278             case EXC_ERR_VALUE: eType = xlErrValue;     break;
279             case EXC_ERR_REF:   eType = xlErrRef;       break;
280             case EXC_ERR_NAME:  eType = xlErrName;      break;
281             case EXC_ERR_NUM:   eType = xlErrNum;       break;
282             case EXC_ERR_NA:    eType = xlErrNA;        break;
283             default:            eType = xlErrUnknown;
284         }
285         rfDblValue = 0.0;
286     }
287     else
288     {
289         // Boolean value
290         eType = nValue ? xlErrTrue : xlErrFalse;
291         rfDblValue = nValue ? 1.0 : 0.0;
292     }
293     return eType;
294 }
295 
GetTwipsFromInch(double fInches)296 sal_uInt16 XclTools::GetTwipsFromInch( double fInches )
297 {
298     return static_cast< sal_uInt16 >(
299         ::std::min( ::std::max( (fInches * EXC_TWIPS_PER_INCH + 0.5), 0.0 ), 65535.0 ) );
300 }
301 
GetTwipsFromHmm(sal_Int32 nHmm)302 sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm )
303 {
304     return GetTwipsFromInch( static_cast< double >( nHmm ) / 1000.0 / CM_PER_INCH );
305 }
306 
GetInchFromTwips(sal_Int32 nTwips)307 double XclTools::GetInchFromTwips( sal_Int32 nTwips )
308 {
309     return static_cast< double >( nTwips ) / EXC_TWIPS_PER_INCH;
310 }
311 
GetInchFromHmm(sal_Int32 nHmm)312 double XclTools::GetInchFromHmm( sal_Int32 nHmm )
313 {
314     return GetInchFromTwips( GetTwipsFromHmm( nHmm ) );
315 }
316 
GetHmmFromInch(double fInches)317 sal_Int32 XclTools::GetHmmFromInch( double fInches )
318 {
319     return static_cast< sal_Int32 >( fInches * CM_PER_INCH * 1000 );
320 }
321 
GetHmmFromTwips(sal_Int32 nTwips)322 sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips )
323 {
324     return GetHmmFromInch( GetInchFromTwips( nTwips ) );
325 }
326 
GetScColumnWidth(sal_uInt16 nXclWidth,long nScCharWidth)327 sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth )
328 {
329     double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth + 0.5;
330     return limit_cast< sal_uInt16 >( fScWidth );
331 }
332 
GetXclColumnWidth(sal_uInt16 nScWidth,long nScCharWidth)333 sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth )
334 {
335     double fXclWidth = static_cast< double >( nScWidth ) * 256.0 / nScCharWidth + 0.5;
336     return limit_cast< sal_uInt16 >( fXclWidth );
337 }
338 
GetXclDefColWidthCorrection(long nXclDefFontHeight)339 double XclTools::GetXclDefColWidthCorrection( long nXclDefFontHeight )
340 {
341     return 40960.0 / ::std::max( nXclDefFontHeight - 15L, 60L ) + 50.0;
342 }
343 
344 // formatting -----------------------------------------------------------------
345 
GetPatternColor(const Color & rPattColor,const Color & rBackColor,sal_uInt16 nXclPattern)346 Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern )
347 {
348     // 0x00 == 0% transparence (full rPattColor)
349     // 0x80 == 100% transparence (full rBackColor)
350     static const sal_uInt8 pnRatioTable[] =
351     {
352         0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40,     // 00 - 07
353         0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48,     // 08 - 15
354         0x50, 0x70, 0x78                                    // 16 - 18
355     };
356     return (nXclPattern < STATIC_ARRAY_SIZE( pnRatioTable )) ?
357         ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor;
358 }
359 
360 // text encoding --------------------------------------------------------------
361 
362 namespace {
363 
364 const struct XclCodePageEntry
365 {
366     sal_uInt16                  mnCodePage;
367     rtl_TextEncoding            meTextEnc;
368 }
369 pCodePageTable[] =
370 {
371     {     437,  RTL_TEXTENCODING_IBM_437        },  // OEM US
372 //  {     720,  RTL_TEXTENCODING_IBM_720        },  // OEM Arabic
373     {     737,  RTL_TEXTENCODING_IBM_737        },  // OEM Greek
374     {     775,  RTL_TEXTENCODING_IBM_775        },  // OEM Baltic
375     {     850,  RTL_TEXTENCODING_IBM_850        },  // OEM Latin I
376     {     852,  RTL_TEXTENCODING_IBM_852        },  // OEM Latin II (Central European)
377     {     855,  RTL_TEXTENCODING_IBM_855        },  // OEM Cyrillic
378     {     857,  RTL_TEXTENCODING_IBM_857        },  // OEM Turkish
379 //  {     858,  RTL_TEXTENCODING_IBM_858        },  // OEM Multilingual Latin I with Euro
380     {     860,  RTL_TEXTENCODING_IBM_860        },  // OEM Portugese
381     {     861,  RTL_TEXTENCODING_IBM_861        },  // OEM Icelandic
382     {     862,  RTL_TEXTENCODING_IBM_862        },  // OEM Hebrew
383     {     863,  RTL_TEXTENCODING_IBM_863        },  // OEM Canadian (French)
384     {     864,  RTL_TEXTENCODING_IBM_864        },  // OEM Arabic
385     {     865,  RTL_TEXTENCODING_IBM_865        },  // OEM Nordic
386     {     866,  RTL_TEXTENCODING_IBM_866        },  // OEM Cyrillic (Russian)
387     {     869,  RTL_TEXTENCODING_IBM_869        },  // OEM Greek (Modern)
388     {     874,  RTL_TEXTENCODING_MS_874         },  // MS Windows Thai
389     {     932,  RTL_TEXTENCODING_MS_932         },  // MS Windows Japanese Shift-JIS
390     {     936,  RTL_TEXTENCODING_MS_936         },  // MS Windows Chinese Simplified GBK
391     {     949,  RTL_TEXTENCODING_MS_949         },  // MS Windows Korean (Wansung)
392     {     950,  RTL_TEXTENCODING_MS_950         },  // MS Windows Chinese Traditional BIG5
393     {    1200,  RTL_TEXTENCODING_DONTKNOW       },  // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page
394     {    1250,  RTL_TEXTENCODING_MS_1250        },  // MS Windows Latin II (Central European)
395     {    1251,  RTL_TEXTENCODING_MS_1251        },  // MS Windows Cyrillic
396     {    1252,  RTL_TEXTENCODING_MS_1252        },  // MS Windows Latin I (BIFF4-BIFF8)
397     {    1253,  RTL_TEXTENCODING_MS_1253        },  // MS Windows Greek
398     {    1254,  RTL_TEXTENCODING_MS_1254        },  // MS Windows Turkish
399     {    1255,  RTL_TEXTENCODING_MS_1255        },  // MS Windows Hebrew
400     {    1256,  RTL_TEXTENCODING_MS_1256        },  // MS Windows Arabic
401     {    1257,  RTL_TEXTENCODING_MS_1257        },  // MS Windows Baltic
402     {    1258,  RTL_TEXTENCODING_MS_1258        },  // MS Windows Vietnamese
403     {    1361,  RTL_TEXTENCODING_MS_1361        },  // MS Windows Korean (Johab)
404     {   10000,  RTL_TEXTENCODING_APPLE_ROMAN    },  // Apple Roman
405     {   32768,  RTL_TEXTENCODING_APPLE_ROMAN    },  // Apple Roman
406     {   32769,  RTL_TEXTENCODING_MS_1252        }   // MS Windows Latin I (BIFF2-BIFF3)
407 };
408 const XclCodePageEntry* const pCodePageTableEnd = STATIC_ARRAY_END( pCodePageTable );
409 
410 struct XclCodePageEntry_CPPred
411 {
XclCodePageEntry_CPPred__anon9b52127e0311::XclCodePageEntry_CPPred412     inline explicit     XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {}
operator ()__anon9b52127e0311::XclCodePageEntry_CPPred413     inline bool         operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; }
414     sal_uInt16          mnCodePage;
415 };
416 
417 struct XclCodePageEntry_TEPred
418 {
XclCodePageEntry_TEPred__anon9b52127e0311::XclCodePageEntry_TEPred419     inline explicit     XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {}
operator ()__anon9b52127e0311::XclCodePageEntry_TEPred420     inline bool         operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; }
421     rtl_TextEncoding    meTextEnc;
422 };
423 
424 } // namespace
425 
GetTextEncoding(sal_uInt16 nCodePage)426 rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage )
427 {
428     const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) );
429     if( pEntry == pCodePageTableEnd )
430     {
431         DBG_ERROR2( "XclTools::GetTextEncoding - unknown code page: 0x%04hX (%d)", nCodePage, nCodePage );
432         return RTL_TEXTENCODING_DONTKNOW;
433     }
434     return pEntry->meTextEnc;
435 }
436 
GetXclCodePage(rtl_TextEncoding eTextEnc)437 sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc )
438 {
439     if( eTextEnc == RTL_TEXTENCODING_UNICODE )
440         return 1200;    // for BIFF8
441 
442     const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) );
443     if( pEntry == pCodePageTableEnd )
444     {
445         DBG_ERROR1( "XclTools::GetXclCodePage - unsupported text encoding: %d", eTextEnc );
446         return 1252;
447     }
448     return pEntry->mnCodePage;
449 }
450 
451 // font names -----------------------------------------------------------------
452 
GetXclFontName(const String & rFontName)453 String XclTools::GetXclFontName( const String& rFontName )
454 {
455     // #106246# substitute with MS fonts
456     String aNewName( GetSubsFontName( rFontName, SUBSFONT_ONLYONE | SUBSFONT_MS ) );
457     if( aNewName.Len() )
458         return aNewName;
459     return rFontName;
460 }
461 
462 // built-in defined names -----------------------------------------------------
463 
464 const String XclTools::maDefNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) );
465 
466 static const sal_Char* const ppcDefNames[] =
467 {
468     "Consolidate_Area",
469     "Auto_Open",
470     "Auto_Close",
471     "Extract",
472     "Database",
473     "Criteria",
474     "Print_Area",
475     "Print_Titles",
476     "Recorder",
477     "Data_Form",
478     "Auto_Activate",
479     "Auto_Deactivate",
480     "Sheet_Title",
481     "_FilterDatabase"
482 };
483 
GetXclBuiltInDefName(sal_Unicode cBuiltIn)484 String XclTools::GetXclBuiltInDefName( sal_Unicode cBuiltIn )
485 {
486     DBG_ASSERT( STATIC_ARRAY_SIZE( ppcDefNames ) == EXC_BUILTIN_UNKNOWN,
487         "XclTools::GetXclBuiltInDefName - built-in defined name list modified" );
488     String aDefName;
489     if( cBuiltIn < STATIC_ARRAY_SIZE( ppcDefNames ) )
490         aDefName.AssignAscii( ppcDefNames[ cBuiltIn ] );
491     else
492         aDefName = String::CreateFromInt32( cBuiltIn );
493     return aDefName;
494 }
495 
GetBuiltInDefName(sal_Unicode cBuiltIn)496 String XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn )
497 {
498     return String( maDefNamePrefix ).Append( GetXclBuiltInDefName( cBuiltIn ) );
499 }
500 
GetBuiltInDefNameIndex(const String & rDefName)501 sal_Unicode XclTools::GetBuiltInDefNameIndex( const String& rDefName )
502 {
503     xub_StrLen nPrefixLen = maDefNamePrefix.Len();
504     if( rDefName.EqualsIgnoreCaseAscii( maDefNamePrefix, 0, nPrefixLen ) )
505     {
506         for( sal_Unicode cBuiltIn = 0; cBuiltIn < EXC_BUILTIN_UNKNOWN; ++cBuiltIn )
507         {
508             String aBuiltInName( GetXclBuiltInDefName( cBuiltIn ) );
509             xub_StrLen nBuiltInLen = aBuiltInName.Len();
510             if( rDefName.EqualsIgnoreCaseAscii( aBuiltInName, nPrefixLen, nBuiltInLen ) )
511             {
512                 // name can be followed by underline or space character
513                 xub_StrLen nNextCharPos = nPrefixLen + nBuiltInLen;
514                 sal_Unicode cNextChar = (rDefName.Len() > nNextCharPos) ? rDefName.GetChar( nNextCharPos ) : '\0';
515                 if( (cNextChar == '\0') || (cNextChar == ' ') || (cNextChar == '_') )
516                     return cBuiltIn;
517             }
518         }
519     }
520     return EXC_BUILTIN_UNKNOWN;
521 }
522 
523 // built-in style names -------------------------------------------------------
524 
525 const String XclTools::maStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) );
526 const String XclTools::maStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "Excel Built-in " ) );
527 
528 static const sal_Char* const ppcStyleNames[] =
529 {
530     "",                 // "Normal" not used directly, but localized "Default"
531     "RowLevel_",        // outline level will be appended
532     "ColumnLevel_",     // outline level will be appended
533     "Comma",
534     "Currency",
535     "Percent",
536     "Comma_0",
537     "Currency_0",
538     "Hyperlink",
539     "Followed_Hyperlink"
540 };
541 
GetBuiltInStyleName(sal_uInt8 nStyleId,const String & rName,sal_uInt8 nLevel)542 String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, const String& rName, sal_uInt8 nLevel )
543 {
544     String aStyleName;
545 
546     if( nStyleId == EXC_STYLE_NORMAL )  // "Normal" becomes "Default" style
547     {
548         aStyleName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
549     }
550     else
551     {
552         aStyleName = maStyleNamePrefix1;
553         if( nStyleId < STATIC_ARRAY_SIZE( ppcStyleNames ) )
554             aStyleName.AppendAscii( ppcStyleNames[ nStyleId ] );
555         else if( rName.Len() > 0 )
556             aStyleName.Append( rName );
557         else
558             aStyleName.Append( String::CreateFromInt32( nStyleId ) );
559         if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
560             aStyleName.Append( String::CreateFromInt32( nLevel + 1 ) );
561     }
562 
563     return aStyleName;
564 }
565 
GetBuiltInStyleName(const String & rStyleName)566 String XclTools::GetBuiltInStyleName( const String& rStyleName )
567 {
568     return String( maStyleNamePrefix1 ).Append( rStyleName );
569 }
570 
IsBuiltInStyleName(const String & rStyleName,sal_uInt8 * pnStyleId,xub_StrLen * pnNextChar)571 bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleId, xub_StrLen* pnNextChar )
572 {
573     // "Default" becomes "Normal"
574     if( rStyleName == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ) )
575     {
576         if( pnStyleId ) *pnStyleId = EXC_STYLE_NORMAL;
577         if( pnNextChar ) *pnNextChar = rStyleName.Len();
578         return true;
579     }
580 
581     // try the other built-in styles
582     sal_uInt8 nFoundId = 0;
583     xub_StrLen nNextChar = 0;
584 
585     xub_StrLen nPrefixLen = 0;
586     if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix1, 0, maStyleNamePrefix1.Len() ) )
587         nPrefixLen = maStyleNamePrefix1.Len();
588     else if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix2, 0, maStyleNamePrefix2.Len() ) )
589         nPrefixLen = maStyleNamePrefix2.Len();
590     if( nPrefixLen > 0 )
591     {
592         String aShortName;
593         for( sal_uInt8 nId = 0; nId < STATIC_ARRAY_SIZE( ppcStyleNames ); ++nId )
594         {
595             if( nId != EXC_STYLE_NORMAL )
596             {
597                 aShortName.AssignAscii( ppcStyleNames[ nId ] );
598                 if( rStyleName.EqualsIgnoreCaseAscii( aShortName, nPrefixLen, aShortName.Len() ) &&
599                     (nNextChar < nPrefixLen + aShortName.Len()) )
600                 {
601                     nFoundId = nId;
602                     nNextChar = nPrefixLen + aShortName.Len();
603                 }
604             }
605         }
606     }
607 
608     if( nNextChar > 0 )
609     {
610         if( pnStyleId ) *pnStyleId = nFoundId;
611         if( pnNextChar ) *pnNextChar = nNextChar;
612         return true;
613     }
614 
615     if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
616     if( pnNextChar ) *pnNextChar = 0;
617     return nPrefixLen > 0;  // also return true for unknown built-in styles
618 }
619 
GetBuiltInStyleId(sal_uInt8 & rnStyleId,sal_uInt8 & rnLevel,const String & rStyleName)620 bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const String& rStyleName )
621 {
622     sal_uInt8 nStyleId;
623     xub_StrLen nNextChar;
624     if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
625     {
626         if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
627         {
628             String aLevel( rStyleName, nNextChar, STRING_LEN );
629             sal_Int32 nLevel = aLevel.ToInt32();
630             if( (String::CreateFromInt32( nLevel ) == aLevel) && (nLevel > 0) && (nLevel <= EXC_STYLE_LEVELCOUNT) )
631             {
632                 rnStyleId = nStyleId;
633                 rnLevel = static_cast< sal_uInt8 >( nLevel - 1 );
634                 return true;
635             }
636         }
637         else if( rStyleName.Len() == nNextChar )
638         {
639             rnStyleId = nStyleId;
640             rnLevel = EXC_STYLE_NOLEVEL;
641             return true;
642         }
643     }
644     rnStyleId = EXC_STYLE_USERDEF;
645     rnLevel = EXC_STYLE_NOLEVEL;
646     return false;
647 }
648 
649 // conditional formatting style names -----------------------------------------
650 
651 const String XclTools::maCFStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_CondFormat_" ) );
652 const String XclTools::maCFStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "ConditionalStyle_" ) );
653 
GetCondFormatStyleName(SCTAB nScTab,sal_Int32 nFormat,sal_uInt16 nCondition)654 String XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition )
655 {
656     return String( maCFStyleNamePrefix1 ).Append( String::CreateFromInt32( nScTab + 1 ) ).
657                 Append( '_' ).Append( String::CreateFromInt32( nFormat + 1 ) ).
658                 Append( '_' ).Append( String::CreateFromInt32( nCondition + 1 ) );
659 }
660 
IsCondFormatStyleName(const String & rStyleName,xub_StrLen * pnNextChar)661 bool XclTools::IsCondFormatStyleName( const String& rStyleName, xub_StrLen* pnNextChar )
662 {
663     xub_StrLen nPrefixLen = 0;
664     if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix1, 0, maCFStyleNamePrefix1.Len() ) )
665         nPrefixLen = maCFStyleNamePrefix1.Len();
666     else if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix2, 0, maCFStyleNamePrefix2.Len() ) )
667         nPrefixLen = maCFStyleNamePrefix2.Len();
668     if( pnNextChar ) *pnNextChar = nPrefixLen;
669     return nPrefixLen > 0;
670 }
671 
672 // stream handling ------------------------------------------------------------
673 
SkipSubStream(XclImpStream & rStrm)674 void XclTools::SkipSubStream( XclImpStream& rStrm )
675 {
676     bool bLoop = true;
677     while( bLoop && rStrm.StartNextRecord() )
678     {
679         sal_uInt16 nRecId = rStrm.GetRecId();
680         bLoop = nRecId != EXC_ID_EOF;
681         if( (nRecId == EXC_ID2_BOF) || (nRecId == EXC_ID3_BOF) || (nRecId == EXC_ID4_BOF) || (nRecId == EXC_ID5_BOF) )
682             SkipSubStream( rStrm );
683     }
684 }
685 
686 // Basic macro names ----------------------------------------------------------
687 
688 const OUString XclTools::maSbMacroPrefix( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:Standard." ) );
689 const OUString XclTools::maSbMacroSuffix( RTL_CONSTASCII_USTRINGPARAM( "?language=Basic&location=document" ) );
690 
GetSbMacroUrl(const String & rMacroName,SfxObjectShell * pDocShell)691 OUString XclTools::GetSbMacroUrl( const String& rMacroName, SfxObjectShell* pDocShell )
692 {
693     OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" );
694     ::ooo::vba::MacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName, false );
695     if( aMacroInfo.mbFound )
696         return ::ooo::vba::makeMacroURL( aMacroInfo.msResolvedMacro );
697     return OUString();
698 }
699 
GetSbMacroUrl(const String & rModuleName,const String & rMacroName,SfxObjectShell * pDocShell)700 OUString XclTools::GetSbMacroUrl( const String& rModuleName, const String& rMacroName, SfxObjectShell* pDocShell )
701 {
702     OSL_ENSURE( rModuleName.Len() > 0, "XclTools::GetSbMacroUrl - module name is empty" );
703     OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" );
704     return GetSbMacroUrl( rModuleName + OUString( sal_Unicode( '.' ) ) + rMacroName, pDocShell );
705 }
706 
GetXclMacroName(const OUString & rSbMacroUrl)707 String XclTools::GetXclMacroName( const OUString& rSbMacroUrl )
708 {
709     sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength();
710     sal_Int32 nMacroNameLen = nSbMacroUrlLen - maSbMacroPrefix.getLength() - maSbMacroSuffix.getLength();
711     if( (nMacroNameLen > 0) && rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroPrefix, 0 ) &&
712             rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroSuffix, nSbMacroUrlLen - maSbMacroSuffix.getLength() ) )
713         return rSbMacroUrl.copy( maSbMacroPrefix.getLength(), nMacroNameLen );
714     return String::EmptyString();
715 }
716 
717 // read/write colors ----------------------------------------------------------
718 
operator >>(XclImpStream & rStrm,Color & rColor)719 XclImpStream& operator>>( XclImpStream& rStrm, Color& rColor )
720 {
721     sal_uInt8 nR, nG, nB, nD;
722     rStrm >> nR >> nG >> nB >> nD;
723     rColor.SetColor( RGB_COLORDATA( nR, nG, nB ) );
724     return rStrm;
725 }
726 
operator <<(XclExpStream & rStrm,const Color & rColor)727 XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor )
728 {
729     return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 );
730 }
731 
732 // ============================================================================
733