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