diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index c163251..25a3387 100644 --- sc/inc/compiler.hxx +++ sc/inc/compiler.hxx @@ -226,6 +226,22 @@ public: parseAnyToken( const String& rFormula, xub_StrLen nSrcPos, const CharClass* pCharClass) const = 0; + + enum SpecialSymbolType + { + /** + * Character between sheet name and address. In OOO A1 this is + * '.', while XL A1 and XL R1C1 this is '!'. + */ + SHEET_SEPARATOR, + + /** + * In OOO A1, a sheet name may be prefixed with '$' to indicate an + * absolute sheet position. + */ + ABS_SHEET_PREFIX + }; + virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const = 0; }; friend struct Convention; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index e9c4a7c..e8b18e9 100644 --- sc/inc/document.hxx +++ sc/inc/document.hxx @@ -567,7 +567,6 @@ SC_DLLPUBLIC ScDBCollection* GetDBCollection() const; void SnapVisArea( Rectangle& rRect ) const; // 1/100 mm SC_DLLPUBLIC BOOL ValidTabName( const String& rName ) const; - static SC_DLLPUBLIC void ConvertToValidTabName( String& rName, sal_Unicode cReplaceChar ); SC_DLLPUBLIC BOOL ValidNewTabName( const String& rName ) const; SC_DLLPUBLIC void CreateValidTabName(String& rName) const; BOOL InsertTab( SCTAB nPos, const String& rName, diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index dbe6130..372fb72 100644 --- sc/source/core/data/document.cxx +++ sc/source/core/data/document.cxx @@ -193,40 +193,34 @@ BOOL ScDocument::GetTable( const String& rName, SCTAB& rTab ) const BOOL ScDocument::ValidTabName( const String& rName ) const { - // behaviour must be equal to ConvertToValidTabName(), see below - using namespace ::com::sun::star::i18n; - sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | - KParseTokens::ASC_UNDERSCORE; - sal_Int32 nContFlags = nStartFlags; - String aContChars( RTL_CONSTASCII_USTRINGPARAM(" ") ); - ParseResult aRes = ScGlobal::pCharClass->parsePredefinedToken( - KParseType::IDENTNAME, rName, 0, nStartFlags, EMPTY_STRING, nContFlags, aContChars ); - return (aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rName.Len(); -} - - -void ScDocument::ConvertToValidTabName( String& rName, sal_Unicode cReplaceChar ) -{ - // behaviour must be equal to ValidTabName(), see above - using namespace ::com::sun::star::i18n; - sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | - KParseTokens::ASC_UNDERSCORE; - sal_Int32 nContFlags = nStartFlags; - String aStartChars; - String aContChars( RTL_CONSTASCII_USTRINGPARAM(" ") ); - sal_Int32 nStartPos = 0; - while( nStartPos < rName.Len() ) + xub_StrLen nLen = rName.Len(); + if (!nLen) + return false; + + for (xub_StrLen i = 0; i < nLen; ++i) { - ParseResult aRes = ScGlobal::pCharClass->parsePredefinedToken( KParseType::IDENTNAME, - rName, nStartPos, nStartFlags, aStartChars, nContFlags, aContChars ); - if( aRes.EndPos < rName.Len() ) + const sal_Unicode c = rName.GetChar(i); + switch (c) { - rName.SetChar( static_cast< xub_StrLen >( aRes.EndPos ), cReplaceChar ); - nStartFlags = nContFlags; - aStartChars = aContChars; + case ':': + case '\\': + case '/': + case '?': + case '*': + case '[': + case ']': + // these characters are not allowed to match XL's convention. + return false; + case '\'': + if (i == 0 || i == nLen - 1) + // single quote is not allowed at the first or last + // character position. + return false; + break; } - nStartPos = aRes.EndPos + 1; } + + return true; } diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx index d2bb670..22815cb 100644 --- sc/source/core/tool/address.cxx +++ sc/source/core/tool/address.cxx @@ -717,23 +717,30 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p, BOOL bExtDoc = FALSE; BOOL bNeedExtTab = FALSE; + //Lets see if this is a reference to something in an external file + //A Documentname is always quoted and has a trailing # if ( *p == '\'' && ScGlobal::UnicodeStrChr( p, SC_COMPILER_FILE_TAB_SEP ) ) { - BOOL bQuote = TRUE; // Dokumentenname ist immer quoted + const sal_Unicode *pStart = p; + BOOL bQuote = TRUE; // A Documentname is always quoted aDocTab += *p++; while ( bQuote && *p ) { if ( *p == '\'' && *(p-1) != '\\' ) bQuote = FALSE; else if( !(*p == '\\' && *(p+1) == '\'') ) - aDocName += *p; // falls escaped Quote: nur Quote in den Namen + aDocName += *p; // An escaped Quote in the Documentname aDocTab += *p++; } aDocTab += *p; // den SC_COMPILER_FILE_TAB_SEP mitnehmen if( *p++ == SC_COMPILER_FILE_TAB_SEP ) bExtDoc = TRUE; else - return nRes; + { + //It wasn't a document after all, reset and continue as normal + p = pStart; + aDocTab = String(); + } } SCCOL nCol = 0; @@ -748,12 +755,33 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p, nRes |= SCA_TAB_ABSOLUTE; if (*p == '$') nRes |= SCA_TAB_ABSOLUTE, p++; - BOOL bQuote = FALSE; + + //Tokens that start at ' can have anything in them until a final ' + //but '' marks an escaped ' + //We've earlier guaranteed that a string containing '' will be + //surrounded by ' if( *p == '\'' ) - p++, bQuote = TRUE; - while (*p && (*p != '.')) { - if( bQuote && *p == '\'' ) + ++p; + while (*p) + { + if (*p == '\'') + { + if ( (*(p+1) != '\'') ) + break; + else + *p++; + } + aTab += *p++; + } + } + + while (*p) + { + if( *p == '.') + break; + + if( *p == '\'' ) { p++; break; } diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index ab91737..d01754f 100644 --- sc/source/core/tool/compiler.cxx +++ sc/source/core/tool/compiler.cxx @@ -1075,6 +1075,34 @@ for (i = 97; i < 123; i++) //----------------------------------------------------------------------------- +static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, ParseResult& rRes ) +{ + //Tokens that start at ' can have anything in them until a final ' + //but '' marks an escaped ' + //We've earlier guaranteed that a string containing '' will be + //surrounded by ' + if (rFormula.GetChar(nSrcPos) == '\'') + { + xub_StrLen nPos = nSrcPos+1; + while (nPos < rFormula.Len()) + { + if (rFormula.GetChar(nPos) == '\'') + { + if ( (nPos+1 == rFormula.Len()) || (rFormula.GetChar(nPos+1) != '\'') ) + { + rRes.TokenType = KParseType::SINGLE_QUOTE_NAME; + rRes.EndPos = nPos+1; + return false; + } + ++nPos; + } + ++nPos; + } + } + + return true; +} + struct Convention_A1 : public ScCompiler::Convention { Convention_A1( ScAddress::Convention eConv ) : ScCompiler::Convention( eConv ) { } @@ -1087,6 +1115,10 @@ struct Convention_A1 : public ScCompiler::Convention xub_StrLen nSrcPos, const CharClass* pCharClass) const { + ParseResult aRet; + if ( !lcl_isValidQuotedText(rFormula, nSrcPos, aRet) ) + return aRet; + static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | KParseTokens::ASC_UNDERSCORE | KParseTokens::ASC_DOLLAR; static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT; @@ -1261,6 +1293,19 @@ struct ConventionOOO_A1 : public Convention_A1 { MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, false); } + + virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const + { + switch (eSymType) + { + case ScCompiler::Convention::ABS_SHEET_PREFIX: + return '$'; + case ScCompiler::Convention::SHEET_SEPARATOR: + return '.'; + } + + return sal_Unicode(0); + } }; @@ -1370,6 +1415,16 @@ struct ConventionXL rBuf.append( sal_Unicode( '!' ) ); } } + + static sal_Unicode getSpecialSymbol( ScCompiler::Convention::SpecialSymbolType eSymType ) + { + switch (eSymType) + { + case ScCompiler::Convention::SHEET_SEPARATOR: + return '!'; + } + return sal_Unicode(0); + } }; struct ConventionXL_A1 : public Convention_A1, public ConventionXL @@ -1446,6 +1501,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL MakeRowStr( rBuf, aRef.Ref2.nRow ); } } + + virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const + { + return ConventionXL::getSpecialSymbol(eSymType); + } }; static const ConventionXL_A1 ConvXL_A1; @@ -1555,6 +1615,10 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL xub_StrLen nSrcPos, const CharClass* pCharClass) const { + ParseResult aRet; + if ( !lcl_isValidQuotedText(rFormula, nSrcPos, aRet) ) + return aRet; + static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | KParseTokens::ASC_UNDERSCORE ; static const sal_Int32 nContFlags = nStartFlags | KParseTokens::ASC_DOT; @@ -1564,6 +1628,11 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL return pCharClass->parseAnyToken( rFormula, nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed ); } + + virtual sal_Unicode getSpecialSymbol( SpecialSymbolType eSymType ) const + { + return ConventionXL::getSpecialSymbol(eSymType); + } }; static const ConventionXL_R1C1 ConvXL_R1C1; @@ -1621,29 +1690,18 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos, void ScCompiler::CheckTabQuotes( String& rString, const ScAddress::Convention eConv ) { - register const xub_StrLen nLen = rString.Len(); - register xub_StrLen i; - - bool bNeedsQuote = false; - - for ( i = 0 ; i < nLen ; i++ ) - { - if( !IsWordChar( rString, i ) ) - { - bNeedsQuote = true; - break; - } - } - if ( !bNeedsQuote && CharClass::isAsciiNumeric( rString ) ) - { - bNeedsQuote = true; - } + using namespace ::com::sun::star::i18n; + sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER | KParseTokens::ASC_UNDERSCORE; + sal_Int32 nContFlags = nStartFlags; + ParseResult aRes = ScGlobal::pCharClass->parsePredefinedToken( + KParseType::IDENTNAME, rString, 0, nStartFlags, EMPTY_STRING, nContFlags, EMPTY_STRING); + bool bNeedsQuote = !((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.Len()); switch ( eConv ) { default : case ScAddress::CONV_UNSPECIFIED : - case ScAddress::CONV_OOO : break; + case ScAddress::CONV_OOO : case ScAddress::CONV_XL_A1 : case ScAddress::CONV_XL_R1C1 : if( bNeedsQuote ) @@ -1756,6 +1814,11 @@ xub_StrLen ScCompiler::NextSymbol() sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0); sal_Unicode cDecSep = (mxSymbols->isEnglish() ? '.' : ScGlobal::pLocaleData->getNumDecimalSep().GetChar(0)); + + // special symbols specific to address convention used + sal_Unicode cSheetPrefix = pConv->getSpecialSymbol(ScCompiler::Convention::ABS_SHEET_PREFIX); + sal_Unicode cSheetSep = pConv->getSpecialSymbol(ScCompiler::Convention::SHEET_SEPARATOR); + int nDecSeps = 0; int nRefInSheetName = 0; mnPredetectedReference = 0; @@ -2063,8 +2126,8 @@ xub_StrLen ScCompiler::NextSymbol() do { bi18n = FALSE; - // special case $'sheetname' - if ( pStart[nSrcPos] == '$' && pStart[nSrcPos+1] == '\'' ) + // special case (e.g. $'sheetname' in OOO A1) + if ( pStart[nSrcPos] == cSheetPrefix && pStart[nSrcPos+1] == '\'' ) aSymbol += pStart[nSrcPos++]; ParseResult aRes = pConv->parseAnyToken( aFormula, nSrcPos, pCharClass ); @@ -2082,9 +2145,9 @@ xub_StrLen ScCompiler::NextSymbol() aSymbol.Append( pStart + nSrcPos, (xub_StrLen)aRes.EndPos - nSrcPos ); nSrcPos = (xub_StrLen) aRes.EndPos; if ( aRes.TokenType & KParseType::SINGLE_QUOTE_NAME ) - { // special cases 'sheetname'. 'filename'# + { // special cases (e.g. 'sheetname'. or 'filename'# in OOO A1) c = pStart[nSrcPos]; - bi18n = (c == '.' || c == SC_COMPILER_FILE_TAB_SEP); + bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP); if ( bi18n ) aSymbol += pStart[nSrcPos++]; } diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx index e92c938..c7dac08 100644 --- sc/source/filter/excel/excimp8.cxx +++ sc/source/filter/excel/excimp8.cxx @@ -186,7 +186,6 @@ void ImportExcel8::Boundsheet( void ) String aName( aIn.ReadUniString( nLen ) ); GetTabInfo().AppendXclTabName( aName, nBdshtTab ); - ScfTools::ConvertToScSheetName( aName ); *pExcRoot->pTabNameBuff << aName; SCTAB nScTab = static_cast< SCTAB >( nBdshtTab ); diff --git a/sc/source/filter/excel/exctools.cxx b/sc/source/filter/excel/exctools.cxx index be44b92..e7cda06 100644 --- sc/source/filter/excel/exctools.cxx +++ sc/source/filter/excel/exctools.cxx @@ -391,7 +391,6 @@ void ExcScenario::Apply( const XclImpRoot& rRoot, const BOOL bLast ) ScDocument& r = rRoot.GetDoc(); ExcScenarioCell* p = EXCSCFIRST(); String aSzenName( *pName ); - ScfTools::ConvertToScSheetName( aSzenName ); UINT16 nNewTab = nTab + 1; if( !r.InsertTab( nNewTab, aSzenName ) ) diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx index 344b648..6bcd443 100644 --- sc/source/filter/excel/impop.cxx +++ sc/source/filter/excel/impop.cxx @@ -435,7 +435,6 @@ void ImportExcel::Externsheet( void ) bool bSameWorkBook; String aEncodedUrl( aIn.ReadByteString( false ) ); XclImpUrlHelper::DecodeUrl( aUrl, aTabName, bSameWorkBook, *pExcRoot->pIR, aEncodedUrl ); - ScfTools::ConvertToScSheetName( aTabName ); pExcRoot->pExtSheetBuff->Add( aUrl, aTabName, bSameWorkBook ); } @@ -686,7 +685,6 @@ void ImportExcel::Boundsheet( void ) } String aName( aIn.ReadByteString( FALSE ) ); - ScfTools::ConvertToScSheetName( aName ); *pExcRoot->pTabNameBuff << aName; diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index fc44f0d..19c8c55 100644 --- sc/source/filter/excel/xicontent.cxx +++ sc/source/filter/excel/xicontent.cxx @@ -354,12 +354,7 @@ void XclImpHyperlink::ConvertToValidTabName(String& rUrl) { bInQuote = !bInQuote; if (!bInQuote && aTabName.Len() > 0) - { - // Sheet name exists. Convert it to valid name the same way the - // sheet names are converted. - ScDocument::ConvertToValidTabName(aTabName, sal_Unicode('_')); aNewUrl.Append(aTabName); - } } else if (bInQuote) aTabName.Append(c); diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index 18daca6..03f988a 100644 --- sc/source/filter/excel/xilink.cxx +++ sc/source/filter/excel/xilink.cxx @@ -422,7 +422,6 @@ XclImpSupbook::XclImpSupbook( XclImpStream& rStrm ) : for( sal_uInt16 nSBTab = 0; nSBTab < nSBTabCnt; ++nSBTab ) { String aTabName( rStrm.ReadUniString() ); - ScfTools::ConvertToScSheetName( aTabName ); maSupbTabList.Append( new XclImpSupbookTab( aTabName ) ); } } diff --git a/sc/source/filter/excel/xipivot.cxx b/sc/source/filter/excel/xipivot.cxx index e0cf43f..d21d90b 100644 --- sc/source/filter/excel/xipivot.cxx +++ sc/source/filter/excel/xipivot.cxx @@ -695,7 +695,6 @@ void XclImpPivotCache::ReadPivotCacheStream( XclImpStream& rStrm ) String aDummyName = CREATE_STRING( "DPCache" ); if( maTabName.Len() > 0 ) aDummyName.Append( '_' ).Append( maTabName ); - ScfTools::ConvertToScSheetName( aDummyName ); rDoc.CreateValidTabName( aDummyName ); rDoc.RenameTab( nScTab, aDummyName ); // set sheet index to source range diff --git a/sc/source/filter/ftools/ftools.cxx b/sc/source/filter/ftools/ftools.cxx index fca755e..8f753e3 100644 --- sc/source/filter/ftools/ftools.cxx +++ sc/source/filter/ftools/ftools.cxx @@ -158,11 +158,6 @@ Color ScfTools::GetMixedColor( const Color& rFore, const Color& rBack, sal_uInt8 // *** conversion of names *** ------------------------------------------------ -void ScfTools::ConvertToScSheetName( String& rName ) -{ - ScDocument::ConvertToValidTabName( rName, '_' ); -} - void ScfTools::ConvertToScDefinedName( String& rName ) { xub_StrLen nLen = rName.Len(); diff --git a/sc/source/filter/inc/ftools.hxx b/sc/source/filter/inc/ftools.hxx index 82ca276..537e7de 100644 --- sc/source/filter/inc/ftools.hxx +++ sc/source/filter/inc/ftools.hxx @@ -292,10 +292,6 @@ public: // *** conversion of names *** ------------------------------------------------ - /** Converts a string to a valid Calc sheet name. - @descr Sheet names in Calc may contain letters, digits, underscores, and spaces - (space characters are not allowed at first position). */ - static void ConvertToScSheetName( String& rName ); /** Converts a string to a valid Calc defined name or database range name. @descr Defined names in Calc may contain letters, digits (*), underscores, periods (*), colons (*), question marks, and dollar signs. diff --git a/sc/source/filter/xcl97/XclImpChangeTrack.cxx b/sc/source/filter/xcl97/XclImpChangeTrack.cxx index 6d1cacd..14b26fa 100644 --- sc/source/filter/xcl97/XclImpChangeTrack.cxx +++ sc/source/filter/xcl97/XclImpChangeTrack.cxx @@ -179,7 +179,6 @@ sal_Bool XclImpChangeTrack::Read3DTabRefInfo( SCTAB& rFirstTab, SCTAB& rLastTab pStrm->Ignore( 1 ); // - sheet name, always separated from URL String aTabName( pStrm->ReadUniString() ); - ScfTools::ConvertToScSheetName( aTabName ); pStrm->Ignore( 1 ); rFirstTab = rLastTab = static_cast(GetLinkManager().GetScTab( aUrl, aTabName )); } diff --git a/sc/source/ui/vba/vbaworksheets.cxx b/sc/source/ui/vba/vbaworksheets.cxx index f7ca487..456dbb6 100644 --- sc/source/ui/vba/vbaworksheets.cxx +++ sc/source/ui/vba/vbaworksheets.cxx @@ -402,9 +402,7 @@ ScVbaWorksheets::Item( const uno::Any& Index, const uno::Any& Index2 ) throw (u uno::Any ScVbaWorksheets::getItemByStringIndex( const rtl::OUString& sIndex ) throw (uno::RuntimeException) { - String sScIndex = sIndex; - ScDocument::ConvertToValidTabName( sScIndex, '_' ); - return ScVbaWorksheets_BASE::getItemByStringIndex( sScIndex ); + return ScVbaWorksheets_BASE::getItemByStringIndex( sIndex ); } rtl::OUString&