summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorIvo Hinkelmann <ihi@openoffice.org>2009-09-17 11:09:25 +0000
committerIvo Hinkelmann <ihi@openoffice.org>2009-09-17 11:09:25 +0000
commitf06e2089d82702cbc577cd3358260d98cc790131 (patch)
tree0e055aab06ec901d42c1b74732f5ee45af6da28b /sc
parente6c032c3a8260f176f8d76c7d29931e119e7a69b (diff)
CWS-TOOLING: integrate CWS dr69
2009-09-09 11:45:28 +0200 dr r275979 : suncc failure 2009-09-09 11:33:34 +0200 dr r275977 : gcc warning 2009-09-09 11:09:02 +0200 er r275976 : #i87171# reworked name check for creating defined names 2009-09-09 10:38:02 +0200 dr r275973 : adapt changes in oox base class 2009-09-09 10:21:03 +0200 dr r275969 : remove faulty pagesize stuff 2009-09-09 10:20:13 +0200 dr r275968 : remove faulty pagesize stuff 2009-09-08 20:24:39 +0200 nn r275958 : #i104899# interpret cells when creating chart listener after loading 2009-09-08 16:05:37 +0200 er r275937 : ScXMLDDELinkContext::EndElement: Excel writes bad ODF <table:dde-link> <table:table> without <table:table-column>'s table:number-columns-repeated attribute; be lenient ... 2009-09-08 13:14:54 +0200 er r275925 : #i103315# handle external references in Excel's ODF msoxl namespace 2009-09-07 17:37:18 +0200 dr r275907 : #i104753# crash when deleting cell with note 2009-09-07 14:02:29 +0200 dr r275896 : #i103520# reworked sheet name buffer to resolve internal hyperlinks, fix almost all remaining problems with external links in BIFF, fix auto color import for BIFF 2009-09-06 20:01:05 +0200 er r275862 : #i35913# fix regression introduced by integration of CWS fhawfixes1; patch from <wsfulton> 2009-09-05 18:32:00 +0200 er r275847 : #i104156# merge #i103918# from uncloned dr68ooo311 2009-09-05 18:19:23 +0200 er r275846 : #i104156# merge #i103317# from uncloned dr68ooo311 2009-09-05 17:32:12 +0200 er r275844 : #i104484# glueState: correct casts in range bounds; patch from <cmc> slightly modified 2009-09-03 17:26:38 +0200 dr r275764 : #i103520# handle apostrophs in sheet names in internal URLs 2009-09-03 17:21:26 +0200 dr r275763 : #i95271# show text formatting in temp notes 2009-09-03 12:24:52 +0200 dr r275747 : unused declaration 2009-09-02 21:33:03 +0200 dr r275727 : #i96438# cleanup color handling in xls filter, extend VML color parser 2009-09-02 15:39:57 +0200 dr r275715 : #158571# #i96438# accept also VML colors in the form '#RRGGBB [xyz]' 2009-09-02 15:16:36 +0200 dr r275714 : #158571# #i96438# set note text 2009-09-02 14:59:33 +0200 dr r275713 : #158571# #i96438# load custom line dashes from DrawingML and VML 2009-09-02 11:53:35 +0200 dr r275702 : #158571# #i96438# import VML fill gradients 2009-08-31 19:28:10 +0200 dr r275632 : #158571# #i96438# more vml formatting 2009-08-31 14:29:30 +0200 dr r275606 : #158571# #i96438# changed handling of xml token ids/names 2009-08-28 18:25:26 +0200 dr r275545 : #158571# #i96438# preparations for and basic support of VML shape formatting, load spreadsheet cell notes position, formatting, and visibility 2009-08-25 19:08:31 +0200 dr r275378 : #i103390# dump BIFF STYLEEXT 2009-08-25 18:28:50 +0200 dr r275377 : #i103390# improve built-in style handling 2009-08-25 18:27:38 +0200 dr r275376 : #i103390# improve built-in style handling 2009-08-04 18:49:40 +0200 dr r274629 : CWS-TOOLING: rebase CWS dr69 to trunk@274622 (milestone: DEV300:m54)
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/compiler.hxx73
-rw-r--r--sc/inc/document.hxx5
-rw-r--r--sc/inc/externalrefmgr.hxx48
-rw-r--r--sc/source/core/data/cell2.cxx4
-rw-r--r--sc/source/core/data/documen3.cxx5
-rw-r--r--sc/source/core/data/document.cxx20
-rw-r--r--sc/source/core/data/postit.cxx25
-rw-r--r--sc/source/core/tool/address.cxx107
-rw-r--r--sc/source/core/tool/compiler.cxx111
-rw-r--r--sc/source/core/tool/rangenam.cxx58
-rw-r--r--sc/source/core/tool/rangeutl.cxx4
-rw-r--r--sc/source/core/tool/reftokenhelper.cxx2
-rw-r--r--sc/source/core/tool/token.cxx2
-rw-r--r--sc/source/filter/excel/xestream.cxx5
-rw-r--r--sc/source/filter/excel/xicontent.cxx19
-rw-r--r--sc/source/filter/excel/xistyle.cxx114
-rw-r--r--sc/source/filter/excel/xltools.cxx42
-rw-r--r--sc/source/filter/ftools/ftools.cxx6
-rw-r--r--sc/source/filter/inc/xestream.hxx1
-rw-r--r--sc/source/filter/inc/xistyle.hxx22
-rw-r--r--sc/source/filter/inc/xlstyle.hxx6
-rw-r--r--sc/source/filter/inc/xltools.hxx8
-rw-r--r--sc/source/filter/xml/XMLDDELinksContext.cxx15
-rw-r--r--sc/source/filter/xml/XMLTableShapeResizer.cxx6
-rw-r--r--sc/source/filter/xml/xmlexprt.cxx2
-rw-r--r--sc/source/filter/xml/xmlexternaltabi.cxx28
-rw-r--r--sc/source/ui/docshell/docfunc.cxx2
-rw-r--r--sc/source/ui/docshell/externalrefmgr.cxx106
-rw-r--r--sc/source/ui/unoobj/chart2uno.cxx14
29 files changed, 671 insertions, 189 deletions
diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx
index 76293479660c..c981af2dad18 100644
--- a/sc/inc/compiler.hxx
+++ b/sc/inc/compiler.hxx
@@ -64,7 +64,7 @@
// constants and data types also for external modules (ScInterpreter et al)
#define MAXCODE 512 /* maximum number of tokens in formula */
-#define MAXSTRLEN 256 /* maximum length of input string of one symbol */
+#define MAXSTRLEN 1024 /* maximum length of input string of one symbol */
#define MAXJUMPCOUNT 32 /* maximum number of jumps (ocChose) */
// flag values of CharTable
@@ -91,6 +91,8 @@
#define SC_COMPILER_C_ODF_RBRACKET 0x00080000 // ODF ']' reference bracket
#define SC_COMPILER_C_ODF_LABEL_OP 0x00100000 // ODF '!!' automatic intersection of labels
#define SC_COMPILER_C_ODF_NAME_MARKER 0x00200000 // ODF '$$' marker that starts a defined (range) name
+#define SC_COMPILER_C_CHAR_NAME 0x00400000 // start character of a defined name
+#define SC_COMPILER_C_NAME 0x00800000 // continuation character of a defined name
#define SC_COMPILER_FILE_TAB_SEP '#' // 'Doc'#Tab
@@ -217,6 +219,14 @@ typedef formula::SimpleIntrusiveReference< struct ScRawToken > ScRawTokenRef;
class SC_DLLPUBLIC ScCompiler : public formula::FormulaCompiler
{
public:
+
+ enum EncodeUrlMode
+ {
+ ENCODE_BY_GRAMMAR,
+ ENCODE_ALWAYS,
+ ENCODE_NEVER,
+ };
+
struct Convention
{
const formula::FormulaGrammar::AddressConvention meConv;
@@ -313,6 +323,7 @@ private:
SCsTAB nMaxTab; // last sheet in document
sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol
const Convention *pConv;
+ EncodeUrlMode meEncodeUrlMode;
bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE
bool mbExtendedErrorDetection;
bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis
@@ -373,6 +384,8 @@ public:
void SetGrammar( const formula::FormulaGrammar::Grammar eGrammar );
+ void SetEncodeUrlMode( EncodeUrlMode eMode );
+ EncodeUrlMode GetEncodeUrlMode() const;
private:
/** Set grammar and reference convention from within SetFormulaLanguage()
or SetGrammar().
@@ -435,28 +448,66 @@ public:
BOOL HasModifiedRange();
- /// If the character is allowed as first character in sheet names or references
+ /** If the character is allowed as first character in sheet names or
+ references, includes '$' and '?'. */
static inline BOOL IsCharWordChar( String const & rStr,
xub_StrLen nPos,
const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO )
{
sal_Unicode c = rStr.GetChar( nPos );
- return c < 128 ?
- static_cast<BOOL>(
- (pConventions[eConv]->mpCharTable[ UINT8(c) ] & SC_COMPILER_C_CHAR_WORD) == SC_COMPILER_C_CHAR_WORD) :
- ScGlobal::pCharClass->isLetterNumeric( rStr, nPos );
+ if (c < 128)
+ {
+ return pConventions[eConv] ? static_cast<BOOL>(
+ (pConventions[eConv]->mpCharTable[ UINT8(c) ] & SC_COMPILER_C_CHAR_WORD) == SC_COMPILER_C_CHAR_WORD) :
+ FALSE; // no convention => assume invalid
+ }
+ else
+ return ScGlobal::pCharClass->isLetterNumeric( rStr, nPos );
}
- /// If the character is allowed in sheet names or references
+ /** If the character is allowed in sheet names, thus may be part of a
+ reference, includes '$' and '?' and such. */
static inline BOOL IsWordChar( String const & rStr,
xub_StrLen nPos,
const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO )
{
sal_Unicode c = rStr.GetChar( nPos );
- return c < 128 ?
- static_cast<BOOL>(
- (pConventions[eConv]->mpCharTable[ UINT8(c) ] & SC_COMPILER_C_WORD) == SC_COMPILER_C_WORD) :
- ScGlobal::pCharClass->isLetterNumeric( rStr, nPos );
+ if (c < 128)
+ {
+ return pConventions[eConv] ? static_cast<BOOL>(
+ (pConventions[eConv]->mpCharTable[ UINT8(c) ] & SC_COMPILER_C_WORD) == SC_COMPILER_C_WORD) :
+ FALSE; // convention not known => assume invalid
+ }
+ else
+ return ScGlobal::pCharClass->isLetterNumeric( rStr, nPos );
+ }
+
+ /** If the character is allowed as tested by nFlags (SC_COMPILER_C_...
+ bits) for all known address conventions. If more than one bit is given
+ in nFlags, all bits must match. If bTestLetterNumeric is FALSE and
+ char>=128, no LetterNumeric test is done and FALSE is returned. */
+ static inline bool IsCharFlagAllConventions( String const & rStr,
+ xub_StrLen nPos,
+ ULONG nFlags,
+ bool bTestLetterNumeric = true )
+ {
+ sal_Unicode c = rStr.GetChar( nPos );
+ if (c < 128)
+ {
+ for ( int nConv = formula::FormulaGrammar::CONV_UNSPECIFIED;
+ ++nConv < formula::FormulaGrammar::CONV_LAST; )
+ {
+ if (pConventions[nConv] &&
+ ((pConventions[nConv]->mpCharTable[ UINT8(c) ] & nFlags) != nFlags))
+ return false;
+ // convention not known => assume valid
+ }
+ return true;
+ }
+ else if (bTestLetterNumeric)
+ return ScGlobal::pCharClass->isLetterNumeric( rStr, nPos );
+ else
+ return false;
}
private:
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 67d36861d10a..5f75108c2ebf 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -610,8 +610,8 @@ public:
const String& aFileName,
const String& aTabName );
- bool HasExternalRefManager() { return pExternalRefMgr.get(); }
- SC_DLLPUBLIC ScExternalRefManager* GetExternalRefManager();
+ bool HasExternalRefManager() const { return pExternalRefMgr.get(); }
+ SC_DLLPUBLIC ScExternalRefManager* GetExternalRefManager() const;
bool IsInExternalReferenceMarking() const;
void MarkUsedExternalReferences();
bool MarkUsedExternalReferences( ScTokenArray & rArr );
@@ -832,6 +832,7 @@ public:
void SetDirty();
void SetDirty( const ScRange& );
void SetTableOpDirty( const ScRange& ); // for Interpreter TableOp
+ void InterpretDirtyCells( const ScRangeList& rRanges );
void CalcAll();
SC_DLLPUBLIC void CalcAfterLoad();
void CompileAll();
diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx
index 9b12dba52f1f..bf795f04fe1c 100644
--- a/sc/inc/externalrefmgr.hxx
+++ b/sc/inc/externalrefmgr.hxx
@@ -422,10 +422,13 @@ public:
/** Source document meta-data container. */
struct SrcFileData
{
- String maFileName;
+ String maFileName; /// original file name as loaded from the file.
+ String maRealFileName; /// file name created from the relative name.
String maRelativeName;
String maFilterName;
String maFilterOptions;
+
+ void maybeCreateRealFileName(const String& rOwnDocName);
};
public:
@@ -576,7 +579,21 @@ public:
*/
void convertToAbsName(String& rFile) const;
sal_uInt16 getExternalFileId(const String& rFile);
- const String* getExternalFileName(sal_uInt16 nFileId) const;
+
+ /**
+ * It returns a pointer to the name of the URI associated with a given
+ * external file ID. In case the original document has moved, it returns
+ * an URI adjusted for the relocation.
+ *
+ * @param nFileId file ID for an external document
+ * @param bForceOriginal If true, it always returns the original document
+ * URI even if the referring document has relocated.
+ * If false, it returns an URI adjusted for
+ * relocated document.
+ *
+ * @return const String* external document URI.
+ */
+ const String* getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal = false);
bool hasExternalFile(sal_uInt16 nFileId) const;
bool hasExternalFile(const String& rFile) const;
const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
@@ -585,8 +602,15 @@ public:
const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
void refreshNames(sal_uInt16 nFileId);
void breakLink(sal_uInt16 nFileId);
- void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter);
+ /**
+ * Set a relative file path for the specified file ID. Note that the
+ * caller must ensure that the passed URL is a valid relative URL.
+ *
+ * @param nFileId file ID for an external document
+ * @param rRelUrl relative URL
+ */
void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
/**
@@ -607,8 +631,11 @@ public:
* Re-generates relative names for all stored source files. This is
* necessary when exporting to an ods document, to ensure that all source
* files have their respective relative names for xlink:href export.
+ *
+ * @param rBaseFileUrl Absolute URL of the content.xml fragment of the
+ * document being exported.
*/
- void resetSrcFileData();
+ void resetSrcFileData(const String& rBaseFileUrl);
/**
* Update a single referencing cell position.
@@ -675,6 +702,19 @@ private:
void maybeLinkExternalFile(sal_uInt16 nFileId);
+ /**
+ * Try to create a "real" file name from the relative path. The original
+ * file name may not point to the real document when the referencing and
+ * referenced documents have been moved.
+ *
+ * For the real file name to be created, the relative name should not be
+ * empty before calling this method, or the real file name will not be
+ * created.
+ *
+ * @param nFileId file ID for an external document
+ */
+ void maybeCreateRealFileName(sal_uInt16 nFileId);
+
bool compileTokensByCell(const ScAddress& rCell);
/**
diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx
index 0b2a5a551ccb..acac874704c6 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -134,8 +134,8 @@ void ScEditCell::GetString( String& rString ) const
EditEngine& rEngine = pDoc->GetEditEngine();
rEngine.SetText( *pData );
rString = ScEditUtil::GetMultilineString(rEngine); // string with line separators between paragraphs
- // kurze Strings fuer Formeln merken
- if ( rString.Len() < MAXSTRLEN )
+ // cache short strings for formulas
+ if ( rString.Len() < 256 )
((ScEditCell*)this)->pString = new String( rString ); //! non-const
}
else
diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx
index 4ba4a225c21f..9fc4b09f21af 100644
--- a/sc/source/core/data/documen3.cxx
+++ b/sc/source/core/data/documen3.cxx
@@ -440,10 +440,11 @@ BOOL ScDocument::LinkExternalTab( SCTAB& rTab, const String& aDocTab,
return TRUE;
}
-ScExternalRefManager* ScDocument::GetExternalRefManager()
+ScExternalRefManager* ScDocument::GetExternalRefManager() const
{
+ ScDocument* pThis = const_cast<ScDocument*>(this);
if (!pExternalRefMgr.get())
- pExternalRefMgr.reset(new ScExternalRefManager(this));
+ pThis->pExternalRefMgr.reset( new ScExternalRefManager( pThis));
return pExternalRefMgr.get();
}
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index c74d804de352..8b04d5a0500e 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -2880,6 +2880,26 @@ void ScDocument::SetTableOpDirty( const ScRange& rRange )
}
+void ScDocument::InterpretDirtyCells( const ScRangeList& rRanges )
+{
+ ULONG nRangeCount = rRanges.Count();
+ for (ULONG nPos=0; nPos<nRangeCount; nPos++)
+ {
+ ScCellIterator aIter( this, *rRanges.GetObject(nPos) );
+ ScBaseCell* pCell = aIter.GetFirst();
+ while (pCell)
+ {
+ if (pCell->GetCellType() == CELLTYPE_FORMULA)
+ {
+ if ( static_cast<ScFormulaCell*>(pCell)->GetDirty() && GetAutoCalc() )
+ static_cast<ScFormulaCell*>(pCell)->Interpret();
+ }
+ pCell = aIter.GetNext();
+ }
+ }
+}
+
+
void ScDocument::AddTableOpFormulaCell( ScFormulaCell* pCell )
{
ScInterpreterTableOpParams* p = aTableOpList.Last();
diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx
index c53694b7674c..a7c5753e4a51 100644
--- a/sc/source/core/data/postit.cxx
+++ b/sc/source/core/data/postit.cxx
@@ -786,19 +786,16 @@ SdrCaptionObj* ScNoteUtil::CreateTempCaption(
OUStringBuffer aBuffer( rUserText );
// add plain text of invisible (!) cell note (no formatting etc.)
SdrCaptionObj* pNoteCaption = 0;
- if( const ScPostIt* pNote = rDoc.GetNote( rPos ) )
+ const ScPostIt* pNote = rDoc.GetNote( rPos );
+ if( pNote && !pNote->IsCaptionShown() )
{
- if( !pNote->IsCaptionShown() )
- {
- if( aBuffer.getLength() > 0 )
- aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) );
- aBuffer.append( pNote->GetText() );
- pNoteCaption = pNote->GetOrCreateCaption( rPos );
- }
+ if( aBuffer.getLength() > 0 )
+ aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) ).append( pNote->GetText() );
+ pNoteCaption = pNote->GetOrCreateCaption( rPos );
}
// create a caption if any text exists
- if( aBuffer.getLength() == 0 )
+ if( !pNoteCaption && (aBuffer.getLength() == 0) )
return 0;
// prepare visible rectangle (add default distance to all borders)
@@ -811,20 +808,24 @@ SdrCaptionObj* ScNoteUtil::CreateTempCaption(
// create the caption object
ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront );
SdrCaptionObj* pCaption = aCreator.GetCaption();
+
// insert caption into page (needed to set caption text)
rDrawPage.InsertObject( pCaption );
- // set the text to the object
- pCaption->SetText( aBuffer.makeStringAndClear() );
- // set formatting (must be done after setting text) and resize the box to fit the text
+ // clone the edit text object, unless user text is present, then set this text
if( pNoteCaption && (rUserText.getLength() == 0) )
{
+ if( OutlinerParaObject* pOPO = pNoteCaption->GetOutlinerParaObject() )
+ pCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) );
+ // set formatting (must be done after setting text) and resize the box to fit the text
pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() );
Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() );
pCaption->SetLogicRect( aCaptRect );
}
else
{
+ // if pNoteCaption is null, then aBuffer contains some text
+ pCaption->SetText( aBuffer.makeStringAndClear() );
ScCaptionUtil::SetDefaultItems( *pCaption, rDoc );
// adjust caption size to text size
long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP );
diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx
index 8bfeaaa72289..259018e213ce 100644
--- a/sc/source/core/tool/address.cxx
+++ b/sc/source/core/tool/address.cxx
@@ -218,18 +218,55 @@ static bool lcl_ScRange_External_TabSpan(
return true;
}
-// Returns NULL if the string should be a sheet name, but is invalid.
-// Returns a pointer to the first character after the sheet name, if there was
-// any, else pointer to start.
+/** Returns NULL if the string should be a sheet name, but is invalid.
+ Returns a pointer to the first character after the sheet name, if there was
+ any, else pointer to start.
+ @param pMsoxlQuoteStop
+ Starting _within_ a quoted name, but still may be 3D; quoted name stops
+ at pMsoxlQuoteStop
+ */
static const sal_Unicode *
lcl_XL_ParseSheetRef( const sal_Unicode* start,
String& rExternTabName,
- bool allow_3d )
+ bool allow_3d,
+ const sal_Unicode* pMsoxlQuoteStop )
{
String aTabName;
const sal_Unicode *p = start;
- if( *p == '\'' ) // XL only seems to use single quotes for sheet names
+ // XL only seems to use single quotes for sheet names.
+ if (pMsoxlQuoteStop)
+ {
+ const sal_Unicode* pCurrentStart = p;
+ while (p < pMsoxlQuoteStop)
+ {
+ if (*p == '\'')
+ {
+ // We pre-analyzed the quoting, no checks needed here.
+ if (*++p == '\'')
+ {
+ aTabName.Append( pCurrentStart,
+ sal::static_int_cast<xub_StrLen>( p - pCurrentStart));
+ pCurrentStart = ++p;
+ }
+ }
+ else if (*p == ':')
+ {
+ break; // while
+ }
+ else
+ ++p;
+ }
+ if (pCurrentStart < p)
+ aTabName.Append( pCurrentStart, sal::static_int_cast<xub_StrLen>( p - pCurrentStart));
+ if (!aTabName.Len())
+ return NULL;
+ if (p == pMsoxlQuoteStop)
+ ++p; // position on ! of ...'!...
+ if( *p != '!' && ( !allow_3d || *p != ':' ) )
+ return (!allow_3d && *p == ':') ? p : start;
+ }
+ else if( *p == '\'')
{
p = lcl_ParseQuotedName(p, aTabName);
if (!aTabName.Len())
@@ -290,8 +327,8 @@ lcl_XL_ParseSheetRef( const sal_Unicode* start,
break;
}
- if( *p != '!' &&( !allow_3d || *p != ':' ) )
- return start;
+ if( *p != '!' && ( !allow_3d || *p != ':' ) )
+ return (!allow_3d && *p == ':') ? p : start;
aTabName.Append( start, sal::static_int_cast<xub_StrLen>( p - start ) );
}
@@ -318,6 +355,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
rStartTabName.Erase();
rEndTabName.Erase();
rExternDocName.Erase();
+ const sal_Unicode* pMsoxlQuoteStop = NULL;
if (*p == '[')
{
++p;
@@ -371,9 +409,47 @@ const sal_Unicode* ScRange::Parse_XL_Header(
}
rExternDocName = ScGlobal::GetAbsDocName(rExternDocName, pDoc->GetDocumentShell());
}
+ else if (*p == '\'')
+ {
+ // Sickness in Excel's ODF msoxl namespace:
+ // 'E:\[EXTDATA8.XLS]Sheet1'!$A$7 or
+ // 'E:\[EXTDATA12B.XLSB]Sheet1:Sheet3'!$A$11
+ // But, 'Sheet1'!B3 would also be a valid!
+ // Excel does not allow [ and ] characters in sheet names though.
+ p = lcl_ParseQuotedName(p, rExternDocName);
+ if (!*p || *p != '!')
+ return start;
+ if (rExternDocName.Len())
+ {
+ xub_StrLen nOpen = rExternDocName.Search( '[');
+ if (nOpen == STRING_NOTFOUND)
+ rExternDocName.Erase();
+ else
+ {
+ xub_StrLen nClose = rExternDocName.Search( ']', nOpen+1);
+ if (nClose == STRING_NOTFOUND)
+ rExternDocName.Erase();
+ else
+ {
+ rExternDocName.Erase( nClose);
+ rExternDocName.Erase( nOpen, 1);
+ pMsoxlQuoteStop = p - 1; // the ' quote char
+ // There may be embedded escaped quotes, just matching the
+ // doc name's length may not work.
+ for (p = start; *p != '['; ++p)
+ ;
+ for ( ; *p != ']'; ++p)
+ ;
+ ++p;
+ }
+ }
+ }
+ if (!rExternDocName.Len())
+ p = start;
+ }
startTabs = p;
- p = lcl_XL_ParseSheetRef( p, rStartTabName, !bOnlyAcceptSingle );
+ p = lcl_XL_ParseSheetRef( p, rStartTabName, !bOnlyAcceptSingle, pMsoxlQuoteStop);
if( NULL == p )
return start; // invalid tab
if (bOnlyAcceptSingle && *p == ':')
@@ -383,7 +459,7 @@ const sal_Unicode* ScRange::Parse_XL_Header(
nFlags |= SCA_VALID_TAB | SCA_TAB_3D | SCA_TAB_ABSOLUTE;
if( *p == ':' ) // 3d ref
{
- p = lcl_XL_ParseSheetRef( p+1, rEndTabName, false );
+ p = lcl_XL_ParseSheetRef( p+1, rEndTabName, false, pMsoxlQuoteStop);
if( p == NULL )
{
nFlags = nSaveFlags;
@@ -413,7 +489,12 @@ const sal_Unicode* ScRange::Parse_XL_Header(
// Use the current tab, it needs to be passed in. : aEnd.SetTab( .. );
}
- if (!rExternDocName.Len())
+ if (rExternDocName.Len())
+ {
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pRefMgr->convertToAbsName( rExternDocName);
+ }
+ else
{
// Internal reference.
if (!rStartTabName.Len())
@@ -594,7 +675,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
if (p && p[0] != 0)
{
// any trailing invalid character must invalidate the whole address.
- nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB);
+ nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
+ SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2);
return nFlags;
}
@@ -661,7 +743,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
if (p && p[0] != 0)
{
// any trailing invalid character must invalidate the whole address.
- nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB);
+ nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
+ SCA_VALID_COL2 | SCA_VALID_ROW2 | SCA_VALID_TAB2);
return nFlags;
}
diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx
index 0da842e6ca5a..a8ca4be2b5b6 100644
--- a/sc/source/core/tool/compiler.cxx
+++ b/sc/source/core/tool/compiler.cxx
@@ -372,6 +372,15 @@ void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar )
}
}
+void ScCompiler::SetEncodeUrlMode( EncodeUrlMode eMode )
+{
+ meEncodeUrlMode = eMode;
+}
+
+ScCompiler::EncodeUrlMode ScCompiler::GetEncodeUrlMode() const
+{
+ return meEncodeUrlMode;
+}
void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
{
@@ -461,22 +470,22 @@ ScCompiler::Convention::Convention( FormulaGrammar::AddressConvention eConv )
/* + */ t[43] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
/* , */ t[44] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE;
/* - */ t[45] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_SIGN;
-/* . */ t[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT;
+/* . */ t[46] = SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_VALUE | SC_COMPILER_C_IDENT | SC_COMPILER_C_NAME;
/* / */ t[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
for (i = 48; i < 58; i++)
-/* 0-9 */ t[i] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_WORD | SC_COMPILER_C_VALUE | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_VALUE | SC_COMPILER_C_IDENT;
+/* 0-9 */ t[i] = SC_COMPILER_C_CHAR_VALUE | SC_COMPILER_C_WORD | SC_COMPILER_C_VALUE | SC_COMPILER_C_VALUE_EXP | SC_COMPILER_C_VALUE_VALUE | SC_COMPILER_C_IDENT | SC_COMPILER_C_NAME;
/* : */ t[58] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD;
/* ; */ t[59] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* < */ t[60] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* = */ t[61] = SC_COMPILER_C_CHAR | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* > */ t[62] = SC_COMPILER_C_CHAR_BOOL | SC_COMPILER_C_BOOL | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
-/* ? */ t[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD;
+/* ? */ t[63] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_NAME;
/* @ */ // FREE
for (i = 65; i < 91; i++)
-/* A-Z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/* A-Z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
if (FormulaGrammar::CONV_ODF == meConv)
{
@@ -491,11 +500,11 @@ ScCompiler::Convention::Convention( FormulaGrammar::AddressConvention eConv )
/* ] */ // FREE
}
/* ^ */ t[94] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
-/* _ */ t[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/* _ */ t[95] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
/* ` */ // FREE
for (i = 97; i < 123; i++)
-/* a-z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
+/* a-z */ t[i] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT | SC_COMPILER_C_CHAR_NAME | SC_COMPILER_C_NAME;
/* { */ t[123] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array open
/* | */ t[124] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP; // array row sep (Should be OOo specific)
@@ -995,14 +1004,19 @@ struct ConventionOOO_A1 : public Convention_A1
bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
const String& rTabName, const ScSingleRefData& rRef,
- ScExternalRefManager* pRefMgr, bool bDisplayTabName ) const
+ ScExternalRefManager* pRefMgr, bool bDisplayTabName, bool bEncodeUrl ) const
{
if (bDisplayTabName)
{
String aFile;
const String* p = pRefMgr->getExternalFileName(nFileId);
if (p)
- aFile = *p;
+ {
+ if (bEncodeUrl)
+ aFile = *p;
+ else
+ aFile = INetURLObject::decode(*p, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
+ }
aFile.SearchAndReplaceAllAscii("'", String::CreateFromAscii("''"));
rBuffer.append(sal_Unicode('\''));
@@ -1036,7 +1050,23 @@ struct ConventionOOO_A1 : public Convention_A1
if (bODF)
rBuffer.append( sal_Unicode('['));
- makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef, pRefMgr, true);
+
+ bool bEncodeUrl = true;
+ switch (rCompiler.GetEncodeUrlMode())
+ {
+ case ScCompiler::ENCODE_BY_GRAMMAR:
+ bEncodeUrl = bODF;
+ break;
+ case ScCompiler::ENCODE_ALWAYS:
+ bEncodeUrl = true;
+ break;
+ case ScCompiler::ENCODE_NEVER:
+ bEncodeUrl = false;
+ break;
+ default:
+ ;
+ }
+ makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef, pRefMgr, true, bEncodeUrl);
if (bODF)
rBuffer.append( sal_Unicode(']'));
}
@@ -1058,9 +1088,25 @@ struct ConventionOOO_A1 : public Convention_A1
if (bODF)
rBuffer.append( sal_Unicode('['));
// Ensure that there's always a closing bracket, no premature returns.
+ bool bEncodeUrl = true;
+ switch (rCompiler.GetEncodeUrlMode())
+ {
+ case ScCompiler::ENCODE_BY_GRAMMAR:
+ bEncodeUrl = bODF;
+ break;
+ case ScCompiler::ENCODE_ALWAYS:
+ bEncodeUrl = true;
+ break;
+ case ScCompiler::ENCODE_NEVER:
+ bEncodeUrl = false;
+ break;
+ default:
+ ;
+ }
+
do
{
- if (!makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref1, pRefMgr, true))
+ if (!makeExternalSingleRefStr(rBuffer, nFileId, rTabName, aRef.Ref1, pRefMgr, true, bEncodeUrl))
break;
rBuffer.append(sal_Unicode(':'));
@@ -1086,7 +1132,7 @@ struct ConventionOOO_A1 : public Convention_A1
else if (bODF)
rBuffer.append( sal_Unicode('.')); // need at least the sheet separator in ODF
makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName,
- aRef.Ref2, pRefMgr, bDisplayTabName);
+ aRef.Ref2, pRefMgr, bDisplayTabName, bEncodeUrl);
} while (0);
if (bODF)
rBuffer.append( sal_Unicode(']'));
@@ -1248,7 +1294,7 @@ struct ConventionXL
return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('!'), false);
}
- static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName )
+ static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName, bool bEncodeUrl )
{
// Format that is easier to deal with inside OOo, because we use file
// URL, and all characetrs are allowed. Check if it makes sense to do
@@ -1259,8 +1305,14 @@ struct ConventionXL
rBuffer.append(sal_Unicode('['));
rBuffer.append(sal_Unicode('\''));
- const sal_Unicode* pBuf = rFullName.GetBuffer();
- xub_StrLen nLen = rFullName.Len();
+ String aFullName;
+ if (bEncodeUrl)
+ aFullName = rFullName;
+ else
+ aFullName = INetURLObject::decode(rFullName, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS);
+
+ const sal_Unicode* pBuf = aFullName.GetBuffer();
+ xub_StrLen nLen = aFullName.Len();
for (xub_StrLen i = 0; i < nLen; ++i)
{
const sal_Unicode c = pBuf[i];
@@ -1473,7 +1525,8 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
ScSingleRefData aRef(rRef);
aRef.CalcAbsIfRel(rCompiler.GetPos());
- ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalDocStr(
+ rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
rBuffer.append(sal_Unicode('!'));
@@ -1496,7 +1549,8 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
ScComplexRefData aRef(rRef);
aRef.CalcAbsIfRel(rCompiler.GetPos());
- ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalDocStr(
+ rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
rBuffer.append(sal_Unicode('!'));
@@ -1677,7 +1731,8 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
ScSingleRefData aRef(rRef);
aRef.CalcAbsIfRel(rCompiler.GetPos());
- ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalDocStr(
+ rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
ScRangeStringConverter::AppendTableName(rBuffer, rTabName);
rBuffer.append(sal_Unicode('!'));
@@ -1701,7 +1756,8 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
ScComplexRefData aRef(rRef);
aRef.CalcAbsIfRel(rCompiler.GetPos());
- ConventionXL::makeExternalDocStr(rBuffer, *pFullName);
+ ConventionXL::makeExternalDocStr(
+ rBuffer, *pFullName, rCompiler.GetEncodeUrlMode() == ScCompiler::ENCODE_ALWAYS);
ConventionXL::makeExternalTabNameRange(rBuffer, rTabName, aTabNames, aRef);
rBuffer.append(sal_Unicode('!'));
@@ -1753,6 +1809,7 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra
mnPredetectedReference(0),
mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
+ meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
mbCloseBrackets( true ),
mbExtendedErrorDetection( false ),
mbRewind( false )
@@ -1768,6 +1825,7 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos)
mnPredetectedReference(0),
mnRangeOpPosInSymbol(-1),
pConv( pConvOOO_A1 ),
+ meEncodeUrlMode( ENCODE_BY_GRAMMAR ),
mbCloseBrackets( true ),
mbExtendedErrorDetection( false ),
mbRewind( false )
@@ -2802,6 +2860,23 @@ BOOL ScCompiler::IsReference( const String& rName )
mbRewind = true;
return true; // end all checks
}
+ else
+ {
+ // Special treatment for the 'E:\[doc]Sheet1:Sheet3'!D5 Excel sickness,
+ // mnRangeOpPosInSymbol did not catch the range operator as it is
+ // within a quoted name.
+ switch (pConv->meConv)
+ {
+ case FormulaGrammar::CONV_XL_A1:
+ case FormulaGrammar::CONV_XL_R1C1:
+ case FormulaGrammar::CONV_XL_OOX:
+ if (rName.GetChar(0) == '\'' && IsDoubleReference( rName))
+ return true;
+ break;
+ default:
+ ; // nothing
+ }
+ }
return false;
}
diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx
index 3f0cadbadb7f..7795256dce3c 100644
--- a/sc/source/core/tool/rangenam.cxx
+++ b/sc/source/core/tool/rangenam.cxx
@@ -453,48 +453,45 @@ void ScRangeData::UpdateTabRef(SCTAB nOldTable, USHORT nFlag, SCTAB nNewTable)
}
}
-// wie beim Uebernehmen von Namen in Excel
void ScRangeData::MakeValidName( String& rName ) // static
{
//ScCompiler::InitSymbolsNative();
- // ungueltige Zeichen vorne weglassen
+ // strip leading invalid characters
xub_StrLen nPos = 0;
xub_StrLen nLen = rName.Len();
- while ( nPos < nLen && !ScCompiler::IsWordChar( rName, nPos) )
+ while ( nPos < nLen && !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
++nPos;
if ( nPos>0 )
rName.Erase(0,nPos);
- // wenn vorne ein ungueltiges Anfangszeichen steht, '_' davor
- if ( rName.Len() && !ScCompiler::IsCharWordChar( rName, 0 ) )
+ // if the first character is an invalid start character, precede with '_'
+ if ( rName.Len() && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
rName.Insert('_',0);
- // ungueltige durch '_' ersetzen
+ // replace invalid with '_'
nLen = rName.Len();
for (nPos=0; nPos<nLen; nPos++)
{
- if ( !ScCompiler::IsWordChar( rName, nPos) )
+ if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME) )
rName.SetChar( nPos, '_' );
}
- // Name darf keine Referenz beinhalten, wie in IsNameValid
+ // Ensure that the proposed name is not a reference under any convention,
+ // same as in IsNameValid()
ScAddress aAddr;
- ScRange aRange;
- int nConv = FormulaGrammar::CONV_UNSPECIFIED; // use int so that op++ works
-
- // Ensure that the proposed name is not an address under any convention
- while ( ++nConv != FormulaGrammar::CONV_LAST )
- {
+ ScRange aRange;
+ for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
+ {
ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
- while( aRange.Parse( rName, NULL, details )
- || aAddr.Parse( rName, NULL, details ) )
+ // Don't check Parse on VALID, any partial only VALID may result in
+ // #REF! during compile later!
+ while (aRange.Parse( rName, NULL, details) || aAddr.Parse( rName, NULL, details))
{
- //! Range Parse auch bei Bereich mit ungueltigem Tabellennamen gueltig
- //! Address Parse dito, Name erzeugt deswegen bei Compile ein #REF!
- if ( rName.SearchAndReplace( ':', '_' ) == STRING_NOTFOUND
- && rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
+ //! Range Parse is partially valid also with invalid sheet name,
+ //! Address Parse dito, during compile name would generate a #REF!
+ if ( rName.SearchAndReplace( '.', '_' ) == STRING_NOTFOUND )
rName.Insert('_',0);
}
}
@@ -502,26 +499,25 @@ void ScRangeData::MakeValidName( String& rName ) // static
BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc )
{
- /* If changed, ScfTools::ConvertToScDefinedName (sc/source/filter/ftools/ftools.cxx)
- needs to be changed too. */
+ /* XXX If changed, sc/source/filter/ftools/ftools.cxx
+ * ScfTools::ConvertToScDefinedName needs to be changed too. */
xub_StrLen nPos = 0;
xub_StrLen nLen = rName.Len();
- if ( !nLen || !ScCompiler::IsCharWordChar( rName, nPos++ ) )
+ if ( !nLen || !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_CHAR_NAME ) )
return FALSE;
while ( nPos < nLen )
{
- if ( !ScCompiler::IsWordChar( rName, nPos++ ) )
+ if ( !ScCompiler::IsCharFlagAllConventions( rName, nPos++, SC_COMPILER_C_NAME ) )
return FALSE;
}
- // Parse nicht auf VALID pruefen, es reicht, wenn irgendein Bestandteil
- // erkannt wurde
+ ScAddress aAddr;
ScRange aRange;
- if( aRange.Parse( rName, pDoc ) ) // THIS IS WRONG
- return FALSE;
- else
+ for (int nConv = FormulaGrammar::CONV_UNSPECIFIED; ++nConv < FormulaGrammar::CONV_LAST; )
{
- ScAddress aAddr;
- if ( aAddr.Parse( rName, pDoc ) ) // THIS IS WRONG
+ ScAddress::Details details( static_cast<FormulaGrammar::AddressConvention>( nConv ) );
+ // Don't check Parse on VALID, any partial only VALID may result in
+ // #REF! during compile later!
+ if (aRange.Parse( rName, pDoc, details) || aAddr.Parse( rName, pDoc, details))
return FALSE;
}
return TRUE;
diff --git a/sc/source/core/tool/rangeutl.cxx b/sc/source/core/tool/rangeutl.cxx
index b1654421b12c..4a26a5004799 100644
--- a/sc/source/core/tool/rangeutl.cxx
+++ b/sc/source/core/tool/rangeutl.cxx
@@ -786,7 +786,7 @@ static void lcl_appendCellAddress(
if (rExtInfo.mbExternal)
{
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId);
+ const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo.mnFileId, true);
if (!pFilePath)
return;
@@ -821,7 +821,7 @@ static void lcl_appendCellRangeAddress(
DBG_ASSERT(rExtInfo1.mnFileId == rExtInfo2.mnFileId, "File IDs do not match between 1st and 2nd addresses.");
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId);
+ const String* pFilePath = pRefMgr->getExternalFileName(rExtInfo1.mnFileId, true);
if (!pFilePath)
return;
diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx
index e129abdcf97f..d0f2b8233de0 100644
--- a/sc/source/core/tool/reftokenhelper.cxx
+++ b/sc/source/core/tool/reftokenhelper.cxx
@@ -51,7 +51,7 @@ using ::rtl::OUString;
void ScRefTokenHelper::compileRangeRepresentation(
vector<ScSharedTokenRef>& rRefTokens, const OUString& rRangeStr, ScDocument* pDoc, FormulaGrammar::Grammar eGrammar)
{
- const sal_Unicode cSep = ';';
+ const sal_Unicode cSep = GetScCompilerNativeSymbol(ocSep).GetChar(0);
const sal_Unicode cQuote = '\'';
bool bFailure = false;
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 0f03d31d3fc8..6c5c6a03b773 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -119,7 +119,7 @@ IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
// Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
// Since RawTokens are temporary for the compiler, don't align on 4k and waste memory.
-// ScRawToken size is FixMembers + MAXSTRLEN ~= 264
+// ScRawToken size is FixMembers + MAXSTRLEN + ~4 ~= 1036
IMPL_FIXEDMEMPOOL_NEWDEL( ScRawToken, 8, 4 )
// Some ScDoubleRawToken, FixMembers + sizeof(double) ~= 16
const USHORT nMemPoolDoubleRawToken = 0x0400 / sizeof(ScDoubleRawToken);
diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx
index 45ced68de006..10d23eccdf27 100644
--- a/sc/source/filter/excel/xestream.cxx
+++ b/sc/source/filter/excel/xestream.cxx
@@ -985,11 +985,6 @@ bool XclExpXmlStream::importDocument() throw()
return false;
}
-sal_Int32 XclExpXmlStream::getSchemeClr( sal_Int32 /*nColorSchemeToken*/ ) const
-{
- return -1;
-}
-
oox::vml::Drawing* XclExpXmlStream::getVmlDrawing()
{
return 0;
diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx
index b57297b344dc..7b5fb222a12b 100644
--- a/sc/source/filter/excel/xicontent.cxx
+++ b/sc/source/filter/excel/xicontent.cxx
@@ -377,14 +377,33 @@ void XclImpHyperlink::ConvertToValidTabName(String& rUrl)
String aNewUrl(sal_Unicode('#')), aTabName;
bool bInQuote = false;
+ bool bQuoteTabName = false;
for (xub_StrLen i = 1; i < n; ++i)
{
c = rUrl.GetChar(i);
if (c == sal_Unicode('\''))
{
+ if (bInQuote && i+1 < n && rUrl.GetChar(i+1) == sal_Unicode('\''))
+ {
+ // Two consecutive single quotes ('') signify a single literal
+ // quite. When this occurs, the whole table name needs to be
+ // quoted.
+ bQuoteTabName = true;
+ aTabName.Append(c);
+ aTabName.Append(c);
+ ++i;
+ continue;
+ }
+
bInQuote = !bInQuote;
if (!bInQuote && aTabName.Len() > 0)
+ {
+ if (bQuoteTabName)
+ aNewUrl.Append(sal_Unicode('\''));
aNewUrl.Append(aTabName);
+ if (bQuoteTabName)
+ aNewUrl.Append(sal_Unicode('\''));
+ }
}
else if (bInQuote)
aTabName.Append(c);
diff --git a/sc/source/filter/excel/xistyle.cxx b/sc/source/filter/excel/xistyle.cxx
index 7f1627e89e7f..a83e203c167d 100644
--- a/sc/source/filter/excel/xistyle.cxx
+++ b/sc/source/filter/excel/xistyle.cxx
@@ -1088,26 +1088,25 @@ void XclImpXF::ReadXF( XclImpStream& rStrm )
}
}
-void XclImpXF::SetStyleName( const String& rStyleName )
+void XclImpXF::SetStyleName( const String& rStyleName, bool bBuiltIn, bool bForceCreate )
{
DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
- DBG_ASSERT( rStyleName.Len(), "XclImpXF::SetStyleName - style name empty" );
- if( IsStyleXF() && !maStyleName.Len() )
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXF::SetStyleName - style name empty" );
+ if( IsStyleXF() && (rStyleName.Len() > 0) )
{
maStyleName = rStyleName;
- mbForceCreate = true;
+ mbWasBuiltIn = bBuiltIn;
+ mbForceCreate = bForceCreate;
}
}
-void XclImpXF::SetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
+void XclImpXF::ChangeStyleName( const String& rStyleName )
{
- DBG_ASSERT( IsStyleXF(), "XclImpXF::SetStyleName - not a style XF" );
- if( IsStyleXF() && !maStyleName.Len() )
- {
- mbWasBuiltIn = true;
- maStyleName = XclTools::GetBuiltInStyleName( nStyleId, nLevel );
- mbForceCreate = nStyleId == EXC_STYLE_NORMAL; // force creation of "Default" style
- }
+ DBG_ASSERT( IsStyleXF(), "XclImpXF::ChangeStyleName - not a style XF" );
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXF::ChangeStyleName - new style name empty" );
+ DBG_ASSERT( maStyleName.Len() > 0, "XclImpXF::ChangeStyleName - old style name empty" );
+ if( IsStyleXF() && (rStyleName.Len() > 0) )
+ maStyleName = rStyleName;
}
void XclImpXF::CreateUserStyle()
@@ -1239,6 +1238,7 @@ ScStyleSheet* XclImpXF::CreateStyleSheet()
{
if( !mpStyleSheet && maStyleName.Len() ) // valid name implies style XF
{
+ bool bCreatePattern = false;
// there may be a user-defined "Default" - test on built-in too!
bool bDefStyle = mbWasBuiltIn && (maStyleName == ScGlobal::GetRscString( STR_STYLENAME_STANDARD ));
if( bDefStyle )
@@ -1249,16 +1249,23 @@ ScStyleSheet* XclImpXF::CreateStyleSheet()
mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find(
ScGlobal::GetRscString( STR_STYLENAME_STANDARD ), SFX_STYLE_FAMILY_PARA ) );
DBG_ASSERT( mpStyleSheet, "XclImpXF::CreateStyleSheet - Default style not found" );
+ bCreatePattern = true;
}
else
{
- /* mbWasBuiltIn==true forces renaming of equal-named user defined styles
- to be able to re-export built-in styles correctly. */
- mpStyleSheet = &ScfTools::MakeCellStyleSheet( GetStyleSheetPool(), maStyleName, mbWasBuiltIn );
+ /* #i103281# do not create another style sheet of the same name,
+ if it exists already. This is needed to prevent that styles
+ pasted from clipboard get duplicated over and over. */
+ mpStyleSheet = static_cast< ScStyleSheet* >( GetStyleSheetPool().Find( maStyleName, SFX_STYLE_FAMILY_PARA ) );
+ if( !mpStyleSheet )
+ {
+ mpStyleSheet = &static_cast< ScStyleSheet& >( GetStyleSheetPool().Make( maStyleName, SFX_STYLE_FAMILY_PARA, SFXSTYLEBIT_USERDEF ) );
+ bCreatePattern = true;
+ }
}
// bDefStyle==true omits default pool items in CreatePattern()
- if( mpStyleSheet )
+ if( bCreatePattern && mpStyleSheet )
mpStyleSheet->GetItemSet().Put( CreatePattern( bDefStyle ).GetItemSet() );
}
return mpStyleSheet;
@@ -1274,6 +1281,16 @@ XclImpXFBuffer::XclImpXFBuffer( const XclImpRoot& rRoot ) :
void XclImpXFBuffer::Initialize()
{
maXFList.Clear();
+ maStyleXFs.clear();
+ /* Reserve style names that are built-in in Calc. For BIFF4 workbooks
+ which contain a separate list of styles per sheet, reserve all existing
+ names if current sheet is not the first sheet. This will create unique
+ names for styles in different sheets with the same name. */
+ bool bReserveAll = (GetBiff() == EXC_BIFF4) && (GetCurrScTab() > 0);
+ SfxStyleSheetIterator aStyleIter( GetDoc().GetStyleSheetPool(), SFX_STYLE_FAMILY_PARA );
+ for( SfxStyleSheetBase* pStyleSheet = aStyleIter.First(); pStyleSheet; pStyleSheet = aStyleIter.Next() )
+ if( bReserveAll || !pStyleSheet->IsUserDefined() )
+ maStyleXFs[ pStyleSheet->GetName() ] = 0;
}
void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
@@ -1282,9 +1299,9 @@ void XclImpXFBuffer::ReadXF( XclImpStream& rStrm )
pXF->ReadXF( rStrm );
maXFList.Append( pXF );
+ // set the name of the "Default" cell style (always the first XF in an Excel file)
if( (GetBiff() >= EXC_BIFF3) && (maXFList.Count() == 1) )
- // set the name of the "Default" cell style (always the first XF in an Excel file)
- pXF->SetBuiltInStyleName( EXC_STYLE_NORMAL, 0 );
+ CalcStyleName( *pXF, EXC_STYLE_NORMAL, 0 );
}
void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
@@ -1301,7 +1318,7 @@ void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
{
sal_uInt8 nStyleId, nLevel;
rStrm >> nStyleId >> nLevel;
- pXF->SetBuiltInStyleName( nStyleId, nLevel );
+ CalcStyleName( *pXF, nStyleId, nLevel );
}
else // user-defined styles
{
@@ -1310,8 +1327,20 @@ void XclImpXFBuffer::ReadStyle( XclImpStream& rStrm )
aStyleName = rStrm.ReadByteString( false ); // 8 bit length
else
aStyleName = rStrm.ReadUniString();
- if( aStyleName.Len() ) // #i1624# #i1768# ignore unnamed styles
- pXF->SetStyleName( aStyleName );
+
+ if( aStyleName.Len() > 0 ) // #i1624# #i1768# ignore unnamed styles
+ {
+ // #i103281# check if this is a new built-in style introduced in XL2007
+ bool bBuiltIn = false;
+ if( (GetBiff() == EXC_BIFF8) && (rStrm.GetNextRecId() == EXC_ID_STYLEEXT) && rStrm.StartNextRecord() )
+ {
+ sal_uInt8 nExtFlags;
+ rStrm.Ignore( 12 );
+ rStrm >> nExtFlags;
+ bBuiltIn = ::get_flag( nExtFlags, EXC_STYLEEXT_BUILTIN );
+ }
+ CalcStyleName( *pXF, aStyleName, bBuiltIn );
+ }
}
}
}
@@ -1345,6 +1374,49 @@ void XclImpXFBuffer::ApplyPattern(
}
}
+void XclImpXFBuffer::CalcStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn )
+{
+ DBG_ASSERT( rStyleName.Len() > 0, "XclImpXFBuffer::CalcStyleName - style name empty" );
+ if( rStyleName.Len() > 0 )
+ {
+ String aStyleName = bBuiltIn ? XclTools::GetBuiltInStyleName( rStyleName ) : rStyleName;
+ SetStyleName( rXF, aStyleName, bBuiltIn, !bBuiltIn );
+ }
+}
+
+void XclImpXFBuffer::CalcStyleName( XclImpXF& rXF, sal_uInt8 nStyleId, sal_uInt8 nLevel )
+{
+ // force creation of "Default" style
+ SetStyleName( rXF, XclTools::GetBuiltInStyleName( nStyleId, nLevel ), true, nStyleId == EXC_STYLE_NORMAL );
+}
+
+void XclImpXFBuffer::SetStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn, bool bForceCreate )
+{
+ DBG_ASSERT( rXF.IsStyleXF(), "XclImpXFBuffer::SetStyleName - not a style XF" );
+ if( rXF.IsStyleXF() )
+ {
+ // find an unused name
+ String aUnusedName( rStyleName );
+ sal_Int32 nIndex = 0;
+ while( maStyleXFs.count( aUnusedName ) > 0 )
+ aUnusedName.Assign( rStyleName ).Append( ' ' ).Append( String::CreateFromInt32( ++nIndex ) );
+
+ // move old style to new name, if new style is built-in
+ if( bBuiltIn && (aUnusedName != rStyleName) )
+ {
+ XclImpXF*& rpXF = maStyleXFs[ aUnusedName ];
+ rpXF = maStyleXFs[ rStyleName ];
+ if( rpXF )
+ rpXF->ChangeStyleName( aUnusedName );
+ aUnusedName = rStyleName;
+ }
+
+ // insert new style
+ maStyleXFs[ aUnusedName ] = &rXF;
+ rXF.SetStyleName( aUnusedName, bBuiltIn, bForceCreate );
+ }
+}
+
// Buffer for XF indexes in cells =============================================
IMPL_FIXEDMEMPOOL_NEWDEL( XclImpXFRange, 100, 500 )
diff --git a/sc/source/filter/excel/xltools.cxx b/sc/source/filter/excel/xltools.cxx
index ef38a0037ca0..a84aaba82b90 100644
--- a/sc/source/filter/excel/xltools.cxx
+++ b/sc/source/filter/excel/xltools.cxx
@@ -511,7 +511,8 @@ sal_Unicode XclTools::GetBuiltInDefNameIndex( const String& rDefName )
// built-in style names -------------------------------------------------------
-const String XclTools::maStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_BuiltIn_" ) );
+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[] =
{
@@ -534,7 +535,7 @@ String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
if( nStyleId == EXC_STYLE_NORMAL ) // "Normal" becomes "Default" style
aStyleName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD );
else if( nStyleId < STATIC_TABLE_SIZE( ppcStyleNames ) )
- aStyleName.Assign( maStyleNamePrefix ).AppendAscii( ppcStyleNames[ nStyleId ] );
+ aStyleName.Assign( maStyleNamePrefix1 ).AppendAscii( ppcStyleNames[ nStyleId ] );
if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
aStyleName.Append( String::CreateFromInt32( nLevel + 1 ) );
@@ -542,6 +543,11 @@ String XclTools::GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel )
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"
@@ -553,10 +559,15 @@ bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleI
}
// try the other built-in styles
- xub_StrLen nPrefixLen = maStyleNamePrefix.Len();
sal_uInt8 nFoundId = 0;
xub_StrLen nNextChar = 0;
- if( rStyleName.EqualsIgnoreCaseAscii( maStyleNamePrefix, 0, nPrefixLen ) )
+
+ 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_TABLE_SIZE( ppcStyleNames ); ++nId )
@@ -583,14 +594,14 @@ bool XclTools::IsBuiltInStyleName( const String& rStyleName, sal_uInt8* pnStyleI
if( pnStyleId ) *pnStyleId = EXC_STYLE_USERDEF;
if( pnNextChar ) *pnNextChar = 0;
- return false;
+ 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 ) )
+ if( IsBuiltInStyleName( rStyleName, &nStyleId, &nNextChar ) && (nStyleId != EXC_STYLE_USERDEF) )
{
if( (nStyleId == EXC_STYLE_ROWLEVEL) || (nStyleId == EXC_STYLE_COLLEVEL) )
{
@@ -617,24 +628,25 @@ bool XclTools::GetBuiltInStyleId( sal_uInt8& rnStyleId, sal_uInt8& rnLevel, cons
// conditional formatting style names -----------------------------------------
-const String XclTools::maCFStyleNamePrefix( RTL_CONSTASCII_USTRINGPARAM( "Excel_CondFormat_" ) );
+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( maCFStyleNamePrefix ).Append( String::CreateFromInt32( nScTab + 1 ) ).
+ 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 = maCFStyleNamePrefix.Len();
- if( rStyleName.EqualsIgnoreCaseAscii( maCFStyleNamePrefix, 0, nPrefixLen ) )
- {
- if( pnNextChar ) *pnNextChar = nPrefixLen;
- return true;
- }
- return false;
+ 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 ------------------------------------------------------------
diff --git a/sc/source/filter/ftools/ftools.cxx b/sc/source/filter/ftools/ftools.cxx
index 98faeb9f03d4..2271a8f35d4d 100644
--- a/sc/source/filter/ftools/ftools.cxx
+++ b/sc/source/filter/ftools/ftools.cxx
@@ -160,13 +160,15 @@ Color ScfTools::GetMixedColor( const Color& rFore, const Color& rBack, sal_uInt8
// *** conversion of names *** ------------------------------------------------
+/* XXX As in sc/source/core/tool/rangenam.cxx ScRangeData::IsValidName() */
+
void ScfTools::ConvertToScDefinedName( String& rName )
{
xub_StrLen nLen = rName.Len();
- if( nLen && !ScCompiler::IsCharWordChar( rName, 0 ) )
+ if( nLen && !ScCompiler::IsCharFlagAllConventions( rName, 0, SC_COMPILER_C_CHAR_NAME ) )
rName.SetChar( 0, '_' );
for( xub_StrLen nPos = 1; nPos < nLen; ++nPos )
- if( !ScCompiler::IsWordChar( rName, nPos ) )
+ if( !ScCompiler::IsCharFlagAllConventions( rName, nPos, SC_COMPILER_C_NAME ) )
rName.SetChar( nPos, '_' );
}
diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx
index 44e02d075317..857d756e2133 100644
--- a/sc/source/filter/inc/xestream.hxx
+++ b/sc/source/filter/inc/xestream.hxx
@@ -333,7 +333,6 @@ public:
// only needed for import; ignore
virtual bool importDocument() throw();
- virtual sal_Int32 getSchemeClr( sal_Int32 nColorSchemeToken ) const;
virtual oox::vml::Drawing* getVmlDrawing();
virtual const oox::drawingml::Theme* getCurrentTheme() const;
virtual const oox::drawingml::table::TableStyleListPtr getTableStyles();
diff --git a/sc/source/filter/inc/xistyle.hxx b/sc/source/filter/inc/xistyle.hxx
index fe43aa75c331..2fe3a6ecbc15 100644
--- a/sc/source/filter/inc/xistyle.hxx
+++ b/sc/source/filter/inc/xistyle.hxx
@@ -397,15 +397,13 @@ public:
/** Reads an XF record. */
void ReadXF( XclImpStream& rStrm );
- /** Sets the style name of this XF, if it is a style XF.
- @descr Additionally creates this user-defined style in the Calc document. */
- void SetStyleName( const String& rStyleName );
- /** Sets the style name of this XF from a built-in Excel style, if it is a style XF.
- @descr Does not create the style in the Calc document. This is done on demand
- in CreatePattern(), if the style is really used. */
- void SetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel );
-
+ /** Sets the style name of this XF, if it is a style XF. */
+ void SetStyleName( const String& rStyleName, bool bBuiltIn, bool bForceCreate );
+ /** Changes the style name of this XF, if it is a style XF. */
+ void ChangeStyleName( const String& rStyleName );
+ /** Returns the style name of this XF, if it is a style XF. */
inline const String& GetStyleName() const { return maStyleName; }
+
inline sal_uInt8 GetHorAlign() const { return maAlignment.mnHorAlign; }
inline sal_uInt8 GetVerAlign() const { return maAlignment.mnVerAlign; }
inline sal_uInt16 GetFontIndex() const { return mnXclFont; }
@@ -501,7 +499,15 @@ public:
SCTAB nScTab, const XclImpXFIndex& rXFIndex );
private:
+ void CalcStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn );
+ void CalcStyleName( XclImpXF& rXF, sal_uInt8 nStyleId, sal_uInt8 nLevel );
+ void SetStyleName( XclImpXF& rXF, const String& rStyleName, bool bBuiltIn, bool bForceCreate );
+
+private:
+ typedef ::std::map< String, XclImpXF* > XclImpStyleXFMap;
+
ScfDelList< XclImpXF > maXFList; /// List of contents of all XF record.
+ XclImpStyleXFMap maStyleXFs; /// Maps style names to style XF records.
};
// Buffer for XF indexes in cells =============================================
diff --git a/sc/source/filter/inc/xlstyle.hxx b/sc/source/filter/inc/xlstyle.hxx
index 9d02f0720efc..ebb22c2cb05f 100644
--- a/sc/source/filter/inc/xlstyle.hxx
+++ b/sc/source/filter/inc/xlstyle.hxx
@@ -242,6 +242,12 @@ const sal_uInt8 EXC_STYLE_USERDEF = 0xFF; /// No built-in styl
const sal_uInt8 EXC_STYLE_LEVELCOUNT = 7; /// Number of outline level styles.
const sal_uInt8 EXC_STYLE_NOLEVEL = 0xFF; /// Default value for unused level.
+// (0x0892) STYLEEXT ----------------------------------------------------------
+
+const sal_uInt16 EXC_ID_STYLEEXT = 0x0892;
+
+const sal_uInt8 EXC_STYLEEXT_BUILTIN = 0x01;
+
// Structs and classes ========================================================
// Color data =================================================================
diff --git a/sc/source/filter/inc/xltools.hxx b/sc/source/filter/inc/xltools.hxx
index 459a5c9b3a78..d818fa9e0a89 100644
--- a/sc/source/filter/inc/xltools.hxx
+++ b/sc/source/filter/inc/xltools.hxx
@@ -197,6 +197,8 @@ public:
@param nLevel The zero-based outline level for RowLevel and ColLevel styles.
@return The style name or an empty string, if the parameters are not valid. */
static String GetBuiltInStyleName( sal_uInt8 nStyleId, sal_uInt8 nLevel );
+ /** Returns the passed style name with a special built-in prefix. */
+ static String GetBuiltInStyleName( const String& rStyleName );
/** Returns true, if the passed string is a name of an Excel built-in style.
@param pnStyleId If not 0, the found style identifier will be returned here.
@param pnNextChar If not 0, the index of the char after the evaluated substring will be returned here. */
@@ -230,8 +232,10 @@ public:
// ------------------------------------------------------------------------
private:
static const String maDefNamePrefix; /// Prefix for built-in defined names.
- static const String maStyleNamePrefix; /// Prefix for built-in cell style names.
- static const String maCFStyleNamePrefix; /// Prefix for cond. formatting style names.
+ static const String maStyleNamePrefix1; /// Prefix for built-in cell style names.
+ static const String maStyleNamePrefix2; /// Prefix for built-in cell style names from OOX filter.
+ static const String maCFStyleNamePrefix1; /// Prefix for cond. formatting style names.
+ static const String maCFStyleNamePrefix2; /// Prefix for cond. formatting style names from OOX filter.
};
// read/write colors ----------------------------------------------------------
diff --git a/sc/source/filter/xml/XMLDDELinksContext.cxx b/sc/source/filter/xml/XMLDDELinksContext.cxx
index c0872ae07668..ce77178500bb 100644
--- a/sc/source/filter/xml/XMLDDELinksContext.cxx
+++ b/sc/source/filter/xml/XMLDDELinksContext.cxx
@@ -163,9 +163,20 @@ void ScXMLDDELinkContext::EndElement()
{
if (nPosition > -1 && nColumns && nRows && GetScImport().GetDocument())
{
+ bool bSizeMatch = (static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size());
+ DBG_ASSERT( bSizeMatch, "ScXMLDDELinkContext::EndElement: matrix dimension doesn't match cells count");
+ // Excel writes bad ODF in that it does not write the
+ // table:number-columns-repeated attribute of the
+ // <table:table-column> element, but apparently uses the number of
+ // <table:table-cell> elements within a <table:table-row> element to
+ // determine the column count instead. Be lenient ...
+ if (!bSizeMatch && nColumns == 1)
+ {
+ nColumns = aDDELinkTable.size() / nRows;
+ DBG_ASSERT( static_cast<size_t>(nColumns * nRows) == aDDELinkTable.size(),
+ "ScXMLDDELinkContext::EndElement: adapted matrix dimension doesn't match either");
+ }
ScMatrixRef pMatrix = new ScMatrix( static_cast<SCSIZE>(nColumns), static_cast<SCSIZE>(nRows) );
-
- DBG_ASSERT(static_cast<sal_uInt32>(nColumns * nRows) == aDDELinkTable.size(), "there is a wrong cells count");
sal_Int32 nCol(0);
sal_Int32 nRow(-1);
sal_Int32 nIndex(0);
diff --git a/sc/source/filter/xml/XMLTableShapeResizer.cxx b/sc/source/filter/xml/XMLTableShapeResizer.cxx
index 88c5fbf248b1..ca6d23a6459a 100644
--- a/sc/source/filter/xml/XMLTableShapeResizer.cxx
+++ b/sc/source/filter/xml/XMLTableShapeResizer.cxx
@@ -106,6 +106,12 @@ void ScMyShapeResizer::CreateChartListener(ScDocument* pDoc,
//otherwise the charts keep their first visual representation which was created at a moment where the calc itself was not loaded completly and is incorect therefor
if( (rImport.getImportFlags() & IMPORT_ALL) == IMPORT_ALL )
pCL->SetDirty( TRUE );
+ else
+ {
+ // #i104899# If a formula cell is already dirty, further changes aren't propagated.
+ // This can happen easily now that row heights aren't updated for all sheets.
+ pDoc->InterpretDirtyCells( *pCL->GetRangeList() );
+ }
pCollection->Insert( pCL );
pCL->StartListeningTo();
diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx
index a35a426e4831..df7e99955bfd 100644
--- a/sc/source/filter/xml/xmlexprt.cxx
+++ b/sc/source/filter/xml/xmlexprt.cxx
@@ -3902,7 +3902,7 @@ void ScXMLExport::WriteExternalRefCaches()
return;
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- pRefMgr->resetSrcFileData();
+ pRefMgr->resetSrcFileData(GetOrigFileName());
sal_uInt16 nCount = pRefMgr->getExternalFileCount();
for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
{
diff --git a/sc/source/filter/xml/xmlexternaltabi.cxx b/sc/source/filter/xml/xmlexternaltabi.cxx
index 7eabdff07b9b..b53431843a57 100644
--- a/sc/source/filter/xml/xmlexternaltabi.cxx
+++ b/sc/source/filter/xml/xmlexternaltabi.cxx
@@ -100,6 +100,32 @@ SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
}
+/**
+ * Make sure the URL is a valid relative URL, mainly to avoid storing
+ * absolute URL as relative URL by accident. For now, we only check the first
+ * three characters which are assumed to be always '../', because the relative
+ * URL for an external document is always in reference to the content.xml
+ * fragment of the original document.
+ */
+static bool lcl_isValidRelativeURL(const OUString& rUrl)
+{
+ sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
+ if (n < 3)
+ return false;
+ const sal_Unicode* p = rUrl.getStr();
+ for (sal_Int32 i = 0; i < n; ++i)
+ {
+ sal_Unicode c = p[i];
+ if (i < 2 && c != '.')
+ // the path must begin with '..'
+ return false;
+ else if (i == 2 && c != '/')
+ // a '/' path separator must follow
+ return false;
+ }
+ return true;
+}
+
void ScXMLExternalRefTabSourceContext::EndElement()
{
ScDocument* pDoc = mrScImport.GetDocument();
@@ -107,7 +133,7 @@ void ScXMLExternalRefTabSourceContext::EndElement()
return;
ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
- if (!maRelativeUrl.equals(mrExternalRefInfo.maFileUrl))
+ if (lcl_isValidRelativeURL(maRelativeUrl))
pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
}
diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx
index 608c1c688ea9..5df8db46bd13 100644
--- a/sc/source/ui/docshell/docfunc.cxx
+++ b/sc/source/ui/docshell/docfunc.cxx
@@ -2016,7 +2016,7 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark,
nScenarioCount ++;
pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
- IDF_ALL, FALSE, pUndoDoc );
+ IDF_ALL | IDF_NOCAPTIONS, FALSE, pUndoDoc );
}
}
diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx
index 9cc0b274028e..5cfc833be5dd 100644
--- a/sc/source/ui/docshell/externalrefmgr.cxx
+++ b/sc/source/ui/docshell/externalrefmgr.cxx
@@ -950,9 +950,18 @@ ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nF
ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
{
+ // In API, the index is transported as cached sheet ID of type sal_Int32 in
+ // sheet::SingleReference.Sheet or sheet::ComplexReference.Reference1.Sheet
+ // in a sheet::FormulaToken, choose a sensible value for N/A. Effectively
+ // being 0xffffffff
+ const size_t nNotAvailable = static_cast<size_t>( static_cast<sal_Int32>( -1));
+
DocItem* pDoc = getDocItem(nFileId);
if (!pDoc)
+ {
+ if (pnIndex) *pnIndex = nNotAvailable;
return TableTypeRef();
+ }
DocItem& rDoc = *pDoc;
@@ -966,7 +975,10 @@ ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nF
}
if (!bCreateNew)
+ {
+ if (pnIndex) *pnIndex = nNotAvailable;
return TableTypeRef();
+ }
// Specified table doesn't exist yet. Create one.
nIndex = rDoc.maTables.size();
@@ -1045,7 +1057,7 @@ void ScExternalRefLink::DataChanged(const String& /*rMimeType*/, const Any& /*rV
else
{
// The source document has changed.
- pMgr->switchSrcFile(mnFileId, aFile);
+ pMgr->switchSrcFile(mnFileId, aFile, aFilter);
maFilterName = aFilter;
}
}
@@ -1891,24 +1903,17 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
if (!pFileData)
return NULL;
+ // Always load the document by using the path created from the relative
+ // path. If the referenced document is not there, simply exit. The
+ // original file name should be used only when the relative path is not
+ // given.
String aFile = pFileData->maFileName;
- if (!isFileLoadable(aFile))
- {
- // The original file path is not loadable. Try the relative path.
- // Note that the path is relative to the content.xml substream which
- // is one-level higher than the file itself.
+ maybeCreateRealFileName(nFileId);
+ if (pFileData->maRealFileName.Len())
+ aFile = pFileData->maRealFileName;
- if (!pFileData->maRelativeName.Len())
- return NULL;
-
- INetURLObject aBaseURL(getOwnDocumentName());
- aBaseURL.insertName(OUString::createFromAscii("content.xml"));
- bool bWasAbs = false;
- aFile = aBaseURL.smartRel2Abs(pFileData->maRelativeName, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
- if (!isFileLoadable(aFile))
- // Ok, I've tried both paths but no success. Bail out.
- return NULL;
- }
+ if (!isFileLoadable(aFile))
+ return NULL;
String aOptions;
ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false);
@@ -1960,6 +1965,9 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri
bool ScExternalRefManager::isFileLoadable(const String& rFile) const
{
+ if (!rFile.Len())
+ return false;
+
if (isOwnDocument(rFile))
return false;
@@ -1994,6 +2002,32 @@ void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId)
maLinkedDocs.insert(LinkedDocMap::value_type(nFileId, true));
}
+void ScExternalRefManager::SrcFileData::maybeCreateRealFileName(const String& rOwnDocName)
+{
+ if (!maRelativeName.Len())
+ // No relative path given. Nothing to do.
+ return;
+
+ if (maRealFileName.Len())
+ // Real file name already created. Nothing to do.
+ return;
+
+ // Formulate the absolute file path from the relative path.
+ const String& rRelPath = maRelativeName;
+ INetURLObject aBaseURL(rOwnDocName);
+ aBaseURL.insertName(OUString::createFromAscii("content.xml"));
+ bool bWasAbs = false;
+ maRealFileName = aBaseURL.smartRel2Abs(rRelPath, bWasAbs).GetMainURL(INetURLObject::NO_DECODE);
+}
+
+void ScExternalRefManager::maybeCreateRealFileName(sal_uInt16 nFileId)
+{
+ if (nFileId >= maSrcFiles.size())
+ return;
+
+ maSrcFiles[nFileId].maybeCreateRealFileName(getOwnDocumentName());
+}
+
bool ScExternalRefManager::compileTokensByCell(const ScAddress& rCell)
{
ScBaseCell* pCell;
@@ -2064,12 +2098,20 @@ sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
return static_cast<sal_uInt16>(maSrcFiles.size() - 1);
}
-const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId) const
+const String* ScExternalRefManager::getExternalFileName(sal_uInt16 nFileId, bool bForceOriginal)
{
if (nFileId >= maSrcFiles.size())
return NULL;
- return &maSrcFiles[nFileId].maFileName;
+ if (bForceOriginal)
+ return &maSrcFiles[nFileId].maFileName;
+
+ maybeCreateRealFileName(nFileId);
+
+ if (maSrcFiles[nFileId].maRealFileName.Len())
+ return &maSrcFiles[nFileId].maRealFileName;
+ else
+ return &maSrcFiles[nFileId].maFileName;
}
bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
@@ -2138,10 +2180,17 @@ void ScExternalRefManager::breakLink(sal_uInt16 nFileId)
notifyAllLinkListeners(nFileId, LINK_BROKEN);
}
-void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile, const String& rNewFilter)
{
maSrcFiles[nFileId].maFileName = rNewFile;
maSrcFiles[nFileId].maRelativeName.Erase();
+ maSrcFiles[nFileId].maRealFileName.Erase();
+ if (!maSrcFiles[nFileId].maFilterName.Equals(rNewFilter))
+ {
+ // Filter type has changed.
+ maSrcFiles[nFileId].maFilterName = rNewFilter;
+ maSrcFiles[nFileId].maFilterOptions.Erase();
+ }
refreshNames(nFileId);
}
@@ -2175,19 +2224,18 @@ bool ScExternalRefManager::hasExternalData() const
return !maSrcFiles.empty();
}
-void ScExternalRefManager::resetSrcFileData()
+void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl)
{
- INetURLObject aBaseURL(getOwnDocumentName());
- aBaseURL.insertName(OUString::createFromAscii("content.xml"));
- String aBaseUrlStr = aBaseURL.GetMainURL(INetURLObject::NO_DECODE);
for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
itr != itrEnd; ++itr)
{
- if (!itr->maRelativeName.Len())
- {
- itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
- aBaseUrlStr, itr->maFileName);
- }
+ // Re-generate relative file name from the absolute file name.
+ String aAbsName = itr->maRealFileName;
+ if (!aAbsName.Len())
+ aAbsName = itr->maFileName;
+
+ itr->maRelativeName = URIHelper::simpleNormalizedMakeRelative(
+ rBaseFileUrl, aAbsName);
}
}
diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx
index d63fbb837e44..bdf5317da1bc 100644
--- a/sc/source/ui/unoobj/chart2uno.cxx
+++ b/sc/source/ui/unoobj/chart2uno.cxx
@@ -500,6 +500,10 @@ void Chart2Positioner::glueState()
ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr);
SCCOLROW n1 = aData.Ref1.nCol;
SCCOLROW n2 = aData.Ref2.nCol;
+ if (n1 > MAXCOL)
+ n1 = MAXCOL;
+ if (n2 > MAXCOL)
+ n2 = MAXCOL;
SCCOLROW nTmp = n2 - n1 + 1;
if (n1 < mnStartCol)
mnStartCol = static_cast<SCCOL>(n1);
@@ -510,14 +514,18 @@ void Chart2Positioner::glueState()
n1 = aData.Ref1.nRow;
n2 = aData.Ref2.nRow;
+ if (n1 > MAXROW)
+ n1 = MAXROW;
+ if (n2 > MAXROW)
+ n2 = MAXROW;
nTmp = n2 - n1 + 1;
if (n1 < mnStartRow)
- mnStartRow = static_cast<SCCOL>(n1);
+ mnStartRow = static_cast<SCROW>(n1);
if (n2 > nEndRow)
- nEndRow = static_cast<SCCOL>(n2);
+ nEndRow = static_cast<SCROW>(n2);
if (nTmp > nMaxRows)
- nMaxRows = static_cast<SCCOL>(nTmp);
+ nMaxRows = static_cast<SCROW>(nTmp);
}
// total column size ?