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