| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_sc.hxx" |
| |
| #include <algorithm> |
| #include <math.h> |
| #include <sal/mathconf.h> |
| #include <unotools/fontcvt.hxx> |
| #include <sfx2/objsh.hxx> |
| #include <editeng/editstat.hxx> |
| #include <filter/msfilter/msvbahelper.hxx> |
| #include "xestream.hxx" |
| #include "document.hxx" |
| #include "docuno.hxx" |
| #include "editutil.hxx" |
| #include "formula/errorcodes.hxx" |
| #include "globstr.hrc" |
| #include "xlstyle.hxx" |
| #include "xlname.hxx" |
| #include "xistream.hxx" |
| #include "xiroot.hxx" |
| #include "xltools.hxx" |
| |
| using ::rtl::OUString; |
| |
| // GUID import/export ========================================================= |
| |
| XclGuid::XclGuid() |
| { |
| ::std::fill( mpnData, STATIC_ARRAY_END( mpnData ), 0 ); |
| } |
| |
| XclGuid::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 ) |
| { |
| // convert to little endian -> makes streaming easy |
| UInt32ToSVBT32( nData1, mpnData ); |
| ShortToSVBT16( nData2, mpnData + 4 ); |
| ShortToSVBT16( nData3, mpnData + 6 ); |
| mpnData[ 8 ] = nData41; |
| mpnData[ 9 ] = nData42; |
| mpnData[ 10 ] = nData43; |
| mpnData[ 11 ] = nData44; |
| mpnData[ 12 ] = nData45; |
| mpnData[ 13 ] = nData46; |
| mpnData[ 14 ] = nData47; |
| mpnData[ 15 ] = nData48; |
| } |
| |
| bool operator==( const XclGuid& rCmp1, const XclGuid& rCmp2 ) |
| { |
| return ::std::equal( rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ), rCmp2.mpnData ); |
| } |
| |
| bool operator<( const XclGuid& rCmp1, const XclGuid& rCmp2 ) |
| { |
| return ::std::lexicographical_compare( |
| rCmp1.mpnData, STATIC_ARRAY_END( rCmp1.mpnData ), |
| rCmp2.mpnData, STATIC_ARRAY_END( rCmp2.mpnData ) ); |
| } |
| |
| XclImpStream& operator>>( XclImpStream& rStrm, XclGuid& rGuid ) |
| { |
| rStrm.Read( rGuid.mpnData, 16 ); // mpnData always in little endian |
| return rStrm; |
| } |
| |
| XclExpStream& operator<<( XclExpStream& rStrm, const XclGuid& rGuid ) |
| { |
| rStrm.Write( rGuid.mpnData, 16 ); // mpnData already in little endian |
| return rStrm; |
| } |
| |
| // Excel Tools ================================================================ |
| |
| // GUID's --------------------------------------------------------------------- |
| |
| const XclGuid XclTools::maGuidStdLink( |
| 0x79EAC9D0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); |
| |
| const XclGuid XclTools::maGuidUrlMoniker( |
| 0x79EAC9E0, 0xBAF9, 0x11CE, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B ); |
| |
| const XclGuid XclTools::maGuidFileMoniker( |
| 0x00000303, 0x0000, 0x0000, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 ); |
| |
| // numeric conversion --------------------------------------------------------- |
| |
| double XclTools::GetDoubleFromRK( sal_Int32 nRKValue ) |
| { |
| union |
| { |
| double fVal; |
| sal_math_Double smD; |
| }; |
| fVal = 0.0; |
| |
| if( ::get_flag( nRKValue, EXC_RK_INTFLAG ) ) |
| { |
| sal_Int32 nTemp = nRKValue >> 2; |
| ::set_flag< sal_Int32 >( nTemp, 0xE0000000, nRKValue < 0 ); |
| fVal = nTemp; |
| } |
| else |
| { |
| smD.w32_parts.msw = nRKValue & EXC_RK_VALUEMASK; |
| } |
| |
| if( ::get_flag( nRKValue, EXC_RK_100FLAG ) ) |
| fVal /= 100.0; |
| |
| return fVal; |
| } |
| |
| bool XclTools::GetRKFromDouble( sal_Int32& rnRKValue, double fValue ) |
| { |
| double fFrac, fInt; |
| |
| // integer |
| fFrac = modf( fValue, &fInt ); |
| if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) // 2^29 |
| { |
| rnRKValue = static_cast< sal_Int32 >( fInt ); |
| rnRKValue <<= 2; |
| rnRKValue |= EXC_RK_INT; |
| return true; |
| } |
| |
| // integer/100 |
| fFrac = modf( fValue * 100.0, &fInt ); |
| if( (fFrac == 0.0) && (fInt >= -536870912.0) && (fInt <= 536870911.0) ) |
| { |
| rnRKValue = static_cast< sal_Int32 >( fInt ); |
| rnRKValue <<= 2; |
| rnRKValue |= EXC_RK_INT100; |
| return true; |
| } |
| |
| // double |
| return false; |
| } |
| |
| sal_Int32 XclTools::GetScRotation( sal_uInt16 nXclRot, sal_Int32 nRotForStacked ) |
| { |
| if( nXclRot == EXC_ROT_STACKED ) |
| return nRotForStacked; |
| DBG_ASSERT( nXclRot <= 180, "XclTools::GetScRotation - illegal rotation angle" ); |
| return static_cast< sal_Int32 >( (nXclRot <= 180) ? (100 * ((nXclRot > 90) ? (450 - nXclRot) : nXclRot)) : 0 ); |
| } |
| |
| sal_uInt8 XclTools::GetXclRotation( sal_Int32 nScRot ) |
| { |
| sal_Int32 nXclRot = nScRot / 100; |
| if( (0 <= nXclRot) && (nXclRot <= 90) ) |
| return static_cast< sal_uInt8 >( nXclRot ); |
| if( nXclRot < 180 ) |
| return static_cast< sal_uInt8 >( 270 - nXclRot ); |
| if( nXclRot < 270 ) |
| return static_cast< sal_uInt8 >( nXclRot - 180 ); |
| if( nXclRot < 360 ) |
| return static_cast< sal_uInt8 >( 450 - nXclRot ); |
| return 0; |
| } |
| |
| sal_uInt8 XclTools::GetXclRotFromOrient( sal_uInt8 nXclOrient ) |
| { |
| switch( nXclOrient ) |
| { |
| case EXC_ORIENT_NONE: return EXC_ROT_NONE; |
| case EXC_ORIENT_STACKED: return EXC_ROT_STACKED; |
| case EXC_ORIENT_90CCW: return EXC_ROT_90CCW; |
| case EXC_ORIENT_90CW: return EXC_ROT_90CW; |
| default: DBG_ERRORFILE( "XclTools::GetXclRotFromOrient - unknown text orientation" ); |
| } |
| return EXC_ROT_NONE; |
| } |
| |
| sal_uInt8 XclTools::GetXclOrientFromRot( sal_uInt16 nXclRot ) |
| { |
| if( nXclRot == EXC_ROT_STACKED ) |
| return EXC_ORIENT_STACKED; |
| DBG_ASSERT( nXclRot <= 180, "XclTools::GetXclOrientFromRot - unknown text rotation" ); |
| if( (45 < nXclRot) && (nXclRot <= 90) ) |
| return EXC_ORIENT_90CCW; |
| if( (135 < nXclRot) && (nXclRot <= 180) ) |
| return EXC_ORIENT_90CW; |
| return EXC_ORIENT_NONE; |
| } |
| |
| sal_uInt8 XclTools::GetXclErrorCode( sal_uInt16 nScError ) |
| { |
| using namespace ScErrorCodes; |
| switch( nScError ) |
| { |
| case errIllegalArgument: return EXC_ERR_VALUE; |
| case errIllegalFPOperation: return EXC_ERR_NUM; // maybe DIV/0 or NUM... |
| case errDivisionByZero: return EXC_ERR_DIV0; |
| case errIllegalParameter: return EXC_ERR_VALUE; |
| case errPairExpected: return EXC_ERR_VALUE; |
| case errOperatorExpected: return EXC_ERR_VALUE; |
| case errVariableExpected: return EXC_ERR_VALUE; |
| case errParameterExpected: return EXC_ERR_VALUE; |
| case errNoValue: return EXC_ERR_VALUE; |
| case errCircularReference: return EXC_ERR_VALUE; |
| case errNoCode: return EXC_ERR_NULL; |
| case errNoRef: return EXC_ERR_REF; |
| case errNoName: return EXC_ERR_NAME; |
| case errNoAddin: return EXC_ERR_NAME; |
| case errNoMacro: return EXC_ERR_NAME; |
| case NOTAVAILABLE: return EXC_ERR_NA; |
| } |
| return EXC_ERR_NA; |
| } |
| |
| sal_uInt16 XclTools::GetScErrorCode( sal_uInt8 nXclError ) |
| { |
| using namespace ScErrorCodes; |
| switch( nXclError ) |
| { |
| case EXC_ERR_NULL: return errNoCode; |
| case EXC_ERR_DIV0: return errDivisionByZero; |
| case EXC_ERR_VALUE: return errNoValue; |
| case EXC_ERR_REF: return errNoRef; |
| case EXC_ERR_NAME: return errNoName; |
| case EXC_ERR_NUM: return errIllegalFPOperation; |
| case EXC_ERR_NA: return NOTAVAILABLE; |
| default: DBG_ERRORFILE( "XclTools::GetScErrorCode - unknown error code" ); |
| } |
| return NOTAVAILABLE; |
| } |
| |
| double XclTools::ErrorToDouble( sal_uInt8 nXclError ) |
| { |
| union |
| { |
| double fVal; |
| sal_math_Double smD; |
| }; |
| ::rtl::math::setNan( &fVal ); |
| smD.nan_parts.fraction_lo = GetScErrorCode( nXclError ); |
| return fVal; |
| } |
| |
| XclBoolError XclTools::ErrorToEnum( double& rfDblValue, sal_uInt8 bErrOrBool, sal_uInt8 nValue ) |
| { |
| XclBoolError eType; |
| if( bErrOrBool ) |
| { |
| // error value |
| switch( nValue ) |
| { |
| case EXC_ERR_NULL: eType = xlErrNull; break; |
| case EXC_ERR_DIV0: eType = xlErrDiv0; break; |
| case EXC_ERR_VALUE: eType = xlErrValue; break; |
| case EXC_ERR_REF: eType = xlErrRef; break; |
| case EXC_ERR_NAME: eType = xlErrName; break; |
| case EXC_ERR_NUM: eType = xlErrNum; break; |
| case EXC_ERR_NA: eType = xlErrNA; break; |
| default: eType = xlErrUnknown; |
| } |
| rfDblValue = 0.0; |
| } |
| else |
| { |
| // Boolean value |
| eType = nValue ? xlErrTrue : xlErrFalse; |
| rfDblValue = nValue ? 1.0 : 0.0; |
| } |
| return eType; |
| } |
| |
| sal_uInt16 XclTools::GetTwipsFromInch( double fInches ) |
| { |
| return static_cast< sal_uInt16 >( |
| ::std::min( ::std::max( (fInches * EXC_TWIPS_PER_INCH + 0.5), 0.0 ), 65535.0 ) ); |
| } |
| |
| sal_uInt16 XclTools::GetTwipsFromHmm( sal_Int32 nHmm ) |
| { |
| return GetTwipsFromInch( static_cast< double >( nHmm ) / 1000.0 / CM_PER_INCH ); |
| } |
| |
| double XclTools::GetInchFromTwips( sal_Int32 nTwips ) |
| { |
| return static_cast< double >( nTwips ) / EXC_TWIPS_PER_INCH; |
| } |
| |
| double XclTools::GetInchFromHmm( sal_Int32 nHmm ) |
| { |
| return GetInchFromTwips( GetTwipsFromHmm( nHmm ) ); |
| } |
| |
| sal_Int32 XclTools::GetHmmFromInch( double fInches ) |
| { |
| return static_cast< sal_Int32 >( fInches * CM_PER_INCH * 1000 ); |
| } |
| |
| sal_Int32 XclTools::GetHmmFromTwips( sal_Int32 nTwips ) |
| { |
| return GetHmmFromInch( GetInchFromTwips( nTwips ) ); |
| } |
| |
| sal_uInt16 XclTools::GetScColumnWidth( sal_uInt16 nXclWidth, long nScCharWidth ) |
| { |
| double fScWidth = static_cast< double >( nXclWidth ) / 256.0 * nScCharWidth + 0.5; |
| return limit_cast< sal_uInt16 >( fScWidth ); |
| } |
| |
| sal_uInt16 XclTools::GetXclColumnWidth( sal_uInt16 nScWidth, long nScCharWidth ) |
| { |
| double fXclWidth = static_cast< double >( nScWidth ) * 256.0 / nScCharWidth + 0.5; |
| return limit_cast< sal_uInt16 >( fXclWidth ); |
| } |
| |
| double XclTools::GetXclDefColWidthCorrection( long nXclDefFontHeight ) |
| { |
| return 40960.0 / ::std::max( nXclDefFontHeight - 15L, 60L ) + 50.0; |
| } |
| |
| // formatting ----------------------------------------------------------------- |
| |
| Color XclTools::GetPatternColor( const Color& rPattColor, const Color& rBackColor, sal_uInt16 nXclPattern ) |
| { |
| // 0x00 == 0% transparence (full rPattColor) |
| // 0x80 == 100% transparence (full rBackColor) |
| static const sal_uInt8 pnRatioTable[] = |
| { |
| 0x80, 0x00, 0x40, 0x20, 0x60, 0x40, 0x40, 0x40, // 00 - 07 |
| 0x40, 0x40, 0x20, 0x60, 0x60, 0x60, 0x60, 0x48, // 08 - 15 |
| 0x50, 0x70, 0x78 // 16 - 18 |
| }; |
| return (nXclPattern < STATIC_ARRAY_SIZE( pnRatioTable )) ? |
| ScfTools::GetMixedColor( rPattColor, rBackColor, pnRatioTable[ nXclPattern ] ) : rPattColor; |
| } |
| |
| // text encoding -------------------------------------------------------------- |
| |
| namespace { |
| |
| const struct XclCodePageEntry |
| { |
| sal_uInt16 mnCodePage; |
| rtl_TextEncoding meTextEnc; |
| } |
| pCodePageTable[] = |
| { |
| { 437, RTL_TEXTENCODING_IBM_437 }, // OEM US |
| // { 720, RTL_TEXTENCODING_IBM_720 }, // OEM Arabic |
| { 737, RTL_TEXTENCODING_IBM_737 }, // OEM Greek |
| { 775, RTL_TEXTENCODING_IBM_775 }, // OEM Baltic |
| { 850, RTL_TEXTENCODING_IBM_850 }, // OEM Latin I |
| { 852, RTL_TEXTENCODING_IBM_852 }, // OEM Latin II (Central European) |
| { 855, RTL_TEXTENCODING_IBM_855 }, // OEM Cyrillic |
| { 857, RTL_TEXTENCODING_IBM_857 }, // OEM Turkish |
| // { 858, RTL_TEXTENCODING_IBM_858 }, // OEM Multilingual Latin I with Euro |
| { 860, RTL_TEXTENCODING_IBM_860 }, // OEM Portugese |
| { 861, RTL_TEXTENCODING_IBM_861 }, // OEM Icelandic |
| { 862, RTL_TEXTENCODING_IBM_862 }, // OEM Hebrew |
| { 863, RTL_TEXTENCODING_IBM_863 }, // OEM Canadian (French) |
| { 864, RTL_TEXTENCODING_IBM_864 }, // OEM Arabic |
| { 865, RTL_TEXTENCODING_IBM_865 }, // OEM Nordic |
| { 866, RTL_TEXTENCODING_IBM_866 }, // OEM Cyrillic (Russian) |
| { 869, RTL_TEXTENCODING_IBM_869 }, // OEM Greek (Modern) |
| { 874, RTL_TEXTENCODING_MS_874 }, // MS Windows Thai |
| { 932, RTL_TEXTENCODING_MS_932 }, // MS Windows Japanese Shift-JIS |
| { 936, RTL_TEXTENCODING_MS_936 }, // MS Windows Chinese Simplified GBK |
| { 949, RTL_TEXTENCODING_MS_949 }, // MS Windows Korean (Wansung) |
| { 950, RTL_TEXTENCODING_MS_950 }, // MS Windows Chinese Traditional BIG5 |
| { 1200, RTL_TEXTENCODING_DONTKNOW }, // Unicode (BIFF8) - return *_DONTKNOW to preserve old code page |
| { 1250, RTL_TEXTENCODING_MS_1250 }, // MS Windows Latin II (Central European) |
| { 1251, RTL_TEXTENCODING_MS_1251 }, // MS Windows Cyrillic |
| { 1252, RTL_TEXTENCODING_MS_1252 }, // MS Windows Latin I (BIFF4-BIFF8) |
| { 1253, RTL_TEXTENCODING_MS_1253 }, // MS Windows Greek |
| { 1254, RTL_TEXTENCODING_MS_1254 }, // MS Windows Turkish |
| { 1255, RTL_TEXTENCODING_MS_1255 }, // MS Windows Hebrew |
| { 1256, RTL_TEXTENCODING_MS_1256 }, // MS Windows Arabic |
| { 1257, RTL_TEXTENCODING_MS_1257 }, // MS Windows Baltic |
| { 1258, RTL_TEXTENCODING_MS_1258 }, // MS Windows Vietnamese |
| { 1361, RTL_TEXTENCODING_MS_1361 }, // MS Windows Korean (Johab) |
| { 10000, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman |
| { 32768, RTL_TEXTENCODING_APPLE_ROMAN }, // Apple Roman |
| { 32769, RTL_TEXTENCODING_MS_1252 } // MS Windows Latin I (BIFF2-BIFF3) |
| }; |
| const XclCodePageEntry* const pCodePageTableEnd = STATIC_ARRAY_END( pCodePageTable ); |
| |
| struct XclCodePageEntry_CPPred |
| { |
| inline explicit XclCodePageEntry_CPPred( sal_uInt16 nCodePage ) : mnCodePage( nCodePage ) {} |
| inline bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.mnCodePage == mnCodePage; } |
| sal_uInt16 mnCodePage; |
| }; |
| |
| struct XclCodePageEntry_TEPred |
| { |
| inline explicit XclCodePageEntry_TEPred( rtl_TextEncoding eTextEnc ) : meTextEnc( eTextEnc ) {} |
| inline bool operator()( const XclCodePageEntry& rEntry ) const { return rEntry.meTextEnc == meTextEnc; } |
| rtl_TextEncoding meTextEnc; |
| }; |
| |
| } // namespace |
| |
| rtl_TextEncoding XclTools::GetTextEncoding( sal_uInt16 nCodePage ) |
| { |
| const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_CPPred( nCodePage ) ); |
| if( pEntry == pCodePageTableEnd ) |
| { |
| DBG_ERROR2( "XclTools::GetTextEncoding - unknown code page: 0x%04hX (%d)", nCodePage, nCodePage ); |
| return RTL_TEXTENCODING_DONTKNOW; |
| } |
| return pEntry->meTextEnc; |
| } |
| |
| sal_uInt16 XclTools::GetXclCodePage( rtl_TextEncoding eTextEnc ) |
| { |
| if( eTextEnc == RTL_TEXTENCODING_UNICODE ) |
| return 1200; // for BIFF8 |
| |
| const XclCodePageEntry* pEntry = ::std::find_if( pCodePageTable, pCodePageTableEnd, XclCodePageEntry_TEPred( eTextEnc ) ); |
| if( pEntry == pCodePageTableEnd ) |
| { |
| DBG_ERROR1( "XclTools::GetXclCodePage - unsupported text encoding: %d", eTextEnc ); |
| return 1252; |
| } |
| return pEntry->mnCodePage; |
| } |
| |
| // font names ----------------------------------------------------------------- |
| |
| String XclTools::GetXclFontName( const String& rFontName ) |
| { |
| // #106246# substitute with MS fonts |
| String aNewName( GetSubsFontName( rFontName, SUBSFONT_ONLYONE | SUBSFONT_MS ) ); |
| if( aNewName.Len() ) |
| return aNewName; |
| return rFontName; |
| } |
| |
| // built-in defined names ----------------------------------------------------- |
| |
| const String XclTools::maDefNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) ); |
| |
| static const sal_Char* const ppcDefNames[] = |
| { |
| "Consolidate_Area", |
| "Auto_Open", |
| "Auto_Close", |
| "Extract", |
| "Database", |
| "Criteria", |
| "Print_Area", |
| "Print_Titles", |
| "Recorder", |
| "Data_Form", |
| "Auto_Activate", |
| "Auto_Deactivate", |
| "Sheet_Title", |
| "_FilterDatabase" |
| }; |
| |
| String XclTools::GetXclBuiltInDefName( sal_Unicode cBuiltIn ) |
| { |
| DBG_ASSERT( STATIC_ARRAY_SIZE( ppcDefNames ) == EXC_BUILTIN_UNKNOWN, |
| "XclTools::GetXclBuiltInDefName - built-in defined name list modified" ); |
| String aDefName; |
| if( cBuiltIn < STATIC_ARRAY_SIZE( ppcDefNames ) ) |
| aDefName.AssignAscii( ppcDefNames[ cBuiltIn ] ); |
| else |
| aDefName = String::CreateFromInt32( cBuiltIn ); |
| return aDefName; |
| } |
| |
| String XclTools::GetBuiltInDefName( sal_Unicode cBuiltIn ) |
| { |
| return String( maDefNamePrefix ).Append( GetXclBuiltInDefName( cBuiltIn ) ); |
| } |
| |
| sal_Unicode XclTools::GetBuiltInDefNameIndex( const String& rDefName ) |
| { |
| xub_StrLen nPrefixLen = maDefNamePrefix.Len(); |
| if( rDefName.EqualsIgnoreCaseAscii( maDefNamePrefix, 0, nPrefixLen ) ) |
| { |
| for( sal_Unicode cBuiltIn = 0; cBuiltIn < EXC_BUILTIN_UNKNOWN; ++cBuiltIn ) |
| { |
| String aBuiltInName( GetXclBuiltInDefName( cBuiltIn ) ); |
| xub_StrLen nBuiltInLen = aBuiltInName.Len(); |
| if( rDefName.EqualsIgnoreCaseAscii( aBuiltInName, nPrefixLen, nBuiltInLen ) ) |
| { |
| // name can be followed by underline or space character |
| xub_StrLen nNextCharPos = nPrefixLen + nBuiltInLen; |
| sal_Unicode cNextChar = (rDefName.Len() > nNextCharPos) ? rDefName.GetChar( nNextCharPos ) : '\0'; |
| if( (cNextChar == '\0') || (cNextChar == ' ') || (cNextChar == '_') ) |
| return cBuiltIn; |
| } |
| } |
| } |
| return EXC_BUILTIN_UNKNOWN; |
| } |
| |
| // built-in style names ------------------------------------------------------- |
| |
| const String XclTools::maStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) ); |
| const String XclTools::maStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "Excel Built-in " ) ); |
| |
| static const sal_Char* const ppcStyleNames[] = |
| { |
| "", // "Normal" not used directly, but localized "Default" |
| "RowLevel_", // outline level will be appended |
| "ColumnLevel_", // outline level will be appended |
| "Comma", |
| "Currency", |
| "Percent", |
| "Comma_0", |
| "Currency_0", |
| "Hyperlink", |
| "Followed_Hyperlink" |
| }; |
| |
| String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, const String& rName, sal_uInt8 nLevel ) |
| { |
| String aStyleName; |
| |
| if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style |
| { |
| aStyleName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD ); |
| } |
| else |
| { |
| aStyleName = maStyleNamePrefix1; |
| if( nStyleId < STATIC_ARRAY_SIZE( ppcStyleNames ) ) |
| aStyleName.AppendAscii( ppcStyleNames[ nStyleId ] ); |
| else if( rName.Len() > 0 ) |
| aStyleName.Append( rName ); |
| else |
| aStyleName.Append( String::CreateFromInt32( nStyleId ) ); |
| if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) ) |
| aStyleName.Append( String::CreateFromInt32( nLevel + 1 ) ); |
| } |
| |
| return aStyleName; |
| } |
| |
| String XclTools::GetBuiltInStyleName( const String& rStyleName ) |
| { |
| return String( maStyleNamePrefix1 ).Append( rStyleName ); |
| } |
| |
| bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleId, xub_StrLen* pnNextChar ) |
| { |
| // "Default" becomes "Normal" |
| if( rStyleName == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ) ) |
| { |
| if( pnStyleId ) *pnStyleId = EXC_STYLE_NORMAL; |
| if( pnNextChar ) *pnNextChar = rStyleName.Len(); |
| return true; |
| } |
| |
| // try the other built-in styles |
| sal_uInt8 nFoundId = 0; |
| xub_StrLen nNextChar = 0; |
| |
| xub_StrLen nPrefixLen = 0; |
| if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix1, 0, maStyleNamePrefix1.Len() ) ) |
| nPrefixLen = maStyleNamePrefix1.Len(); |
| else if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix2, 0, maStyleNamePrefix2.Len() ) ) |
| nPrefixLen = maStyleNamePrefix2.Len(); |
| if( nPrefixLen > 0 ) |
| { |
| String aShortName; |
| for( sal_uInt8 nId = 0; nId < STATIC_ARRAY_SIZE( ppcStyleNames ); ++nId ) |
| { |
| if( nId != EXC_STYLE_NORMAL ) |
| { |
| aShortName.AssignAscii( ppcStyleNames[ nId ] ); |
| if( rStyleName.EqualsIgnoreCaseAscii( aShortName, nPrefixLen, aShortName.Len() ) && |
| (nNextChar < nPrefixLen + aShortName.Len()) ) |
| { |
| nFoundId = nId; |
| nNextChar = nPrefixLen + aShortName.Len(); |
| } |
| } |
| } |
| } |
| |
| if( nNextChar > 0 ) |
| { |
| if( pnStyleId ) *pnStyleId = nFoundId; |
| if( pnNextChar ) *pnNextChar = nNextChar; |
| return true; |
| } |
| |
| if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF; |
| if( pnNextChar ) *pnNextChar = 0; |
| return nPrefixLen > 0; // also return true for unknown built-in styles |
| } |
| |
| bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, const String& rStyleName ) |
| { |
| sal_uInt8 nStyleId; |
| xub_StrLen nNextChar; |
| if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) ) |
| { |
| if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) ) |
| { |
| String aLevel( rStyleName, nNextChar, STRING_LEN ); |
| sal_Int32 nLevel = aLevel.ToInt32(); |
| if( (String::CreateFromInt32( nLevel ) == aLevel) && (nLevel > 0) && (nLevel <= EXC_STYLE_LEVELCOUNT) ) |
| { |
| rnStyleId = nStyleId; |
| rnLevel = static_cast< sal_uInt8 >( nLevel - 1 ); |
| return true; |
| } |
| } |
| else if( rStyleName.Len() == nNextChar ) |
| { |
| rnStyleId = nStyleId; |
| rnLevel = EXC_STYLE_NOLEVEL; |
| return true; |
| } |
| } |
| rnStyleId = EXC_STYLE_USERDEF; |
| rnLevel = EXC_STYLE_NOLEVEL; |
| return false; |
| } |
| |
| // conditional formatting style names ----------------------------------------- |
| |
| const String XclTools::maCFStyleNamePrefix1( RTL_CONSTASCII_USTRINGPARAM( "Excel_CondFormat_" ) ); |
| const String XclTools::maCFStyleNamePrefix2( RTL_CONSTASCII_USTRINGPARAM( "ConditionalStyle_" ) ); |
| |
| String XclTools::GetCondFormatStyleName( SCTAB nScTab, sal_Int32 nFormat, sal_uInt16 nCondition ) |
| { |
| return String( maCFStyleNamePrefix1 ).Append( String::CreateFromInt32( nScTab + 1 ) ). |
| Append( '_' ).Append( String::CreateFromInt32( nFormat + 1 ) ). |
| Append( '_' ).Append( String::CreateFromInt32( nCondition + 1 ) ); |
| } |
| |
| bool XclTools::IsCondFormatStyleName( const String& rStyleName, xub_StrLen* pnNextChar ) |
| { |
| xub_StrLen nPrefixLen = 0; |
| if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix1, 0, maCFStyleNamePrefix1.Len() ) ) |
| nPrefixLen = maCFStyleNamePrefix1.Len(); |
| else if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix2, 0, maCFStyleNamePrefix2.Len() ) ) |
| nPrefixLen = maCFStyleNamePrefix2.Len(); |
| if( pnNextChar ) *pnNextChar = nPrefixLen; |
| return nPrefixLen > 0; |
| } |
| |
| // stream handling ------------------------------------------------------------ |
| |
| void XclTools::SkipSubStream( XclImpStream& rStrm ) |
| { |
| bool bLoop = true; |
| while( bLoop && rStrm.StartNextRecord() ) |
| { |
| sal_uInt16 nRecId = rStrm.GetRecId(); |
| bLoop = nRecId != EXC_ID_EOF; |
| if( (nRecId == EXC_ID2_BOF) || (nRecId == EXC_ID3_BOF) || (nRecId == EXC_ID4_BOF) || (nRecId == EXC_ID5_BOF) ) |
| SkipSubStream( rStrm ); |
| } |
| } |
| |
| // Basic macro names ---------------------------------------------------------- |
| |
| const OUString XclTools::maSbMacroPrefix( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.script:Standard." ) ); |
| const OUString XclTools::maSbMacroSuffix( RTL_CONSTASCII_USTRINGPARAM( "?language=Basic&location=document" ) ); |
| |
| OUString XclTools::GetSbMacroUrl( const String& rMacroName, SfxObjectShell* pDocShell ) |
| { |
| OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" ); |
| ::ooo::vba::MacroResolvedInfo aMacroInfo = ::ooo::vba::resolveVBAMacro( pDocShell, rMacroName, false ); |
| if( aMacroInfo.mbFound ) |
| return ::ooo::vba::makeMacroURL( aMacroInfo.msResolvedMacro ); |
| return OUString(); |
| } |
| |
| OUString XclTools::GetSbMacroUrl( const String& rModuleName, const String& rMacroName, SfxObjectShell* pDocShell ) |
| { |
| OSL_ENSURE( rModuleName.Len() > 0, "XclTools::GetSbMacroUrl - module name is empty" ); |
| OSL_ENSURE( rMacroName.Len() > 0, "XclTools::GetSbMacroUrl - macro name is empty" ); |
| return GetSbMacroUrl( rModuleName + OUString( sal_Unicode( '.' ) ) + rMacroName, pDocShell ); |
| } |
| |
| String XclTools::GetXclMacroName( const OUString& rSbMacroUrl ) |
| { |
| sal_Int32 nSbMacroUrlLen = rSbMacroUrl.getLength(); |
| sal_Int32 nMacroNameLen = nSbMacroUrlLen - maSbMacroPrefix.getLength() - maSbMacroSuffix.getLength(); |
| if( (nMacroNameLen > 0) && rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroPrefix, 0 ) && |
| rSbMacroUrl.matchIgnoreAsciiCase( maSbMacroSuffix, nSbMacroUrlLen - maSbMacroSuffix.getLength() ) ) |
| return rSbMacroUrl.copy( maSbMacroPrefix.getLength(), nMacroNameLen ); |
| return String::EmptyString(); |
| } |
| |
| // read/write colors ---------------------------------------------------------- |
| |
| XclImpStream& operator>>( XclImpStream& rStrm, Color& rColor ) |
| { |
| sal_uInt8 nR, nG, nB, nD; |
| rStrm >> nR >> nG >> nB >> nD; |
| rColor.SetColor( RGB_COLORDATA( nR, nG, nB ) ); |
| return rStrm; |
| } |
| |
| XclExpStream& operator<<( XclExpStream& rStrm, const Color& rColor ) |
| { |
| return rStrm << rColor.GetRed() << rColor.GetGreen() << rColor.GetBlue() << sal_uInt8( 0 ); |
| } |
| |
| // ============================================================================ |