ooo-build r15074 - in branches/ooo-build-3-0-1: . patches/dev300
- From: kyoshida svn gnome org
- To: svn-commits-list gnome org
- Subject: ooo-build r15074 - in branches/ooo-build-3-0-1: . patches/dev300
- Date: Thu, 15 Jan 2009 02:44:24 +0000 (UTC)
Author: kyoshida
Date: Thu Jan 15 02:44:24 2009
New Revision: 15074
URL: http://svn.gnome.org/viewvc/ooo-build?rev=15074&view=rev
Log:
2009-01-14 Kohei Yoshida <kyoshida novell com>
* patches/dev300/calc-external-defined-names-officecfg.diff:
* patches/dev300/calc-external-defined-names-svtools.diff:
* patches/dev300/calc-external-defined-names-offapi.diff:
* patches/dev300/calc-external-defined-names-sc.diff:
* patches/dev300/apply: ported the above patches from trunk, but they
are in CalcExperimental section which is disabled by default.
Added:
branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff
branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff
Modified:
branches/ooo-build-3-0-1/ChangeLog
branches/ooo-build-3-0-1/patches/dev300/apply
branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff
branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff
Modified: branches/ooo-build-3-0-1/patches/dev300/apply
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/apply (original)
+++ branches/ooo-build-3-0-1/patches/dev300/apply Thu Jan 15 02:44:24 2009
@@ -30,7 +30,8 @@
Experimental: VBAUntested, ArkOnlyExperimental, SharedWorksheets, \
UnUsedButNotYetRemovedFromSVN, WebDAVUpstream, \
PostgreSQL, SELinux, VOSremoval, Glib2, \
- UnitBootstrap, RadioButtons, UnstableLibwpd, WWInProgress, KDE4
+ UnitBootstrap, RadioButtons, UnstableLibwpd, WWInProgress, KDE4 \
+ CalcExperimental
DebianLooseSections: DebianBaseNoHelpContent
# Optional sections
Optional : DejaVuFonts, NovellOnlyExtensionFixes, Win32OnlyExtensionFixes, Linux32OnlyExtensionFixes
@@ -1793,10 +1794,6 @@
# to xls.
chart-subtitle-xls-export.diff, i#92357, kohei
-# Implement external range names.
-#calc-external-defined-names-sc.diff, i#3740, i#4385, n#355685, kohei
-#calc-external-defined-names-offapi.diff, i#3740, i#4385, n#355685, kohei
-
# fix bug generating a specific Sheet reference
parse-xla1-bad-3dflag.diff, n#422569, noelpwer
@@ -1812,6 +1809,15 @@
# fix 'Identify Categories' greakage on grouping.
calc-dp-group-ident-category-fix.diff, n#447182, i#96171, kohei
+[ CalcExperimental ]
+
+# Implement external range names.
+calc-external-defined-names-sc.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-offapi.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-svtools.diff, i#3740, i#4385, n#355685, kohei
+calc-external-defined-names-officecfg.diff, i#3740, i#4385, n#355685, kohei
+
+
[ CalcSolver ]
SectionOwner => kohei
Modified: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff (original)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-offapi.diff Thu Jan 15 02:44:24 2009
@@ -1,3 +1,17 @@
+diff --git offapi/com/sun/star/sheet/DatabaseRange.idl offapi/com/sun/star/sheet/DatabaseRange.idl
+index 4bbb5f5..6e66ba4 100644
+--- offapi/com/sun/star/sheet/DatabaseRange.idl
++++ offapi/com/sun/star/sheet/DatabaseRange.idl
+@@ -154,7 +154,8 @@ published service DatabaseRange
+ /** returns the index used to refer to this range in token arrays.
+
+ <p>A token describing a database range shall contain the op-code
+- OPCODE_DB_AREA and this index as data part.</p>
++ obtained from the <const>FormulaMapGroupSpecialOffset::DB_AREA</const>
++ and this index as data part.</p>
+
+ @see com::sun::star::sheet::FormulaToken
+ @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::DB_AREA
diff --git offapi/com/sun/star/sheet/ExternalDocLink.idl offapi/com/sun/star/sheet/ExternalDocLink.idl
new file mode 100644
index 0000000..9c7f70d
@@ -284,10 +298,10 @@
+
diff --git offapi/com/sun/star/sheet/ExternalReference.idl offapi/com/sun/star/sheet/ExternalReference.idl
new file mode 100644
-index 0000000..a2bc3c7
+index 0000000..7686310
--- /dev/null
+++ offapi/com/sun/star/sheet/ExternalReference.idl
-@@ -0,0 +1,90 @@
+@@ -0,0 +1,99 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -325,47 +339,56 @@
+
+//=============================================================================
+
-+/** Data structure to store information about an external reference. An
++/** Data structure to store information about an external reference. An
+ external reference can be either a single cell reference, a cell range
+ reference, or a named range.
+
++ @see FormulaMapGroupSpecialOffset::PUSH
++
+ @since OOo 3.1
+ */
+struct ExternalReference
+{
+ //-------------------------------------------------------------------------
+
-+ /** Index of an externally linked document. Each externally-linked document
++ /** Index of an externally linked document. Each externally-linked document
+ has a unique index value.
-+
-+ <p>You can get the index value of an external document from the
-+ corresponding <type scope="com::sun::star::sheet">ExternalDocLink</type>
++
++ <p>You can get the index value of an external document from the
++ corresponding <type scope="com::sun::star::sheet">ExternalDocLink</type>
+ instance through its attribute <type scope="com::sun::star::sheet::ExternalDocLink">TokenIndex</type>.</p>
+
+ @see com::sun::star::sheet::ExternalDocLink
+ @see com::sun::star::sheet::ExternalDocLink::TokenIndex
+ */
+ long Index;
-+
++
++#if 0
+ //-------------------------------------------------------------------------
+
+ /** Name of the sheet that the external reference points to.
+
-+ <p>In case of a cell range reference that spans across multiple
++ <p>In case of a cell range reference that spans across multiple
+ sheets, this is the name of the first sheet in that range.</p>
+
-+ <p>Note that an external range name ignores this value at the moment,
-+ but <i>it may make use of this data in the future when Calc supports a
++ <p>Note that an external range name ignores this value at the moment,
++ but <i>it may make use of this data in the future when Calc supports a
+ sheet-specific range name.</i></p>
+ */
+ string SheetName;
++#endif
+
+ //-------------------------------------------------------------------------
+
-+ /** Reference data. This can store either <type scope="com::sun::star::sheet">SingleReference</type>
-+ for a single cell reference, <type scope="com::sun::star::sheet">ComplexReference</type>
-+ for a cell range reference, or simply a <type>string</type> for a range
-+ name.
++ /** Reference data.
++
++ <p>This can store either <type>SingleReference</type> for a single
++ cell reference, <type>ComplexReference</type> for a cell range
++ reference, or simply a <type>string</type> for a defined name.</p>
++
++ <p>The <member>SingleReference::Sheet</member> member shall contain
++ the index of the external sheet cache containing the values of the
++ externally referenced cells.</p>
+
+ @see com::sun::star::sheet::SingleReference
+ @see com::sun::star::sheet::ComplexReference
@@ -439,25 +462,249 @@
+}; }; }; };
+
+#endif
+diff --git offapi/com/sun/star/sheet/FormulaMapGroup.idl offapi/com/sun/star/sheet/FormulaMapGroup.idl
+index c128585..e846d72 100644
+--- offapi/com/sun/star/sheet/FormulaMapGroup.idl
++++ offapi/com/sun/star/sheet/FormulaMapGroup.idl
+@@ -47,7 +47,10 @@ module com { module sun { module star { module sheet {
+ */
+ constants FormulaMapGroup
+ {
+- /** Group of op-codes without a string symbol */
++ /** Group of op-codes without a string symbol.
++
++ @see FormulaMapGroupSpecialOffset
++ */
+ const long SPECIAL = 0;
+
+ /** Separators and parentheses */
diff --git offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
-index 20369b2..6fa02d0 100644
+index 20369b2..7ebfe52 100644
--- offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
+++ offapi/com/sun/star/sheet/FormulaMapGroupSpecialOffset.idl
-@@ -59,6 +59,8 @@ constants FormulaMapGroupSpecialOffset
+@@ -31,37 +31,182 @@
+ #ifndef __com_sun_star_sheet_FormulaMapGroupSpecialOffset_idl__
+ #define __com_sun_star_sheet_FormulaMapGroupSpecialOffset_idl__
+
+-//=============================================================================
++// ===========================================================================
+
+ module com { module sun { module star { module sheet {
+
+-//=============================================================================
++// ===========================================================================
+
+ /** Constants designating the offsets within the sequence returned by
+ <member>XFormurmulaOpCodeMapper::getAvailableMappings</member> when
+- called for group <type>FormulaMapGroup</type> SPECIAL.
++ called for group <const>FormulaMapGroup::SPECIAL</const>.
+
+ The number of constants may grow in future versions!
+ */
+ constants FormulaMapGroupSpecialOffset
+ {
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe a formula operand token that will be pushed onto the formula
++ stack while the formula is interpreted.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain one of
++ the following values:</p>
++
++ <ul>
++ <li>A value of type <atom>double</atom> for literal floating-point
++ constants.</li>
++ <li>A <atom>string</atom> for literal text.</li>
++ <li>A sequence of sequence of <atom>any</atom> for a literal array.
++ The contained values shall be of type <atom>double</atom> or
++ <atom>string</atom>. Floating-point values and strings may occur
++ together in an array.</li>
++ <li>A struct of type <type>SingleReference</type> for a reference to a
++ single cell in the own document.</li>
++ <li>A struct of type <type>ComplexReference</type> for a reference to
++ a range of cells in the own document.</li>
++ <li>A struct of type <type>ExternalReference</type> for a reference to
++ a cell, a range of cells, or a defined name in an external
++ document.</li>
++ </ul>
++ */
+ const long PUSH = 0;
++
++ // -----------------------------------------------------------------------
++
+ const long CALL = 1;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ instruct the formula interpreter to immediately stop interpreting the
++ formula.
++
++ <p>The <member>FormulaToken::Data</member> member is not used
++ and should be empty.</p>
++ */
+ const long STOP = 2;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe the reference to an external function (e.g. add-in function)
++ used in formulas.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain a
++ <atom>string</atom> with the programmatical name of the function, e.g.
++ "com.sun.star.sheet.addin.Analysis.getEomonth" for the EOMONTH
++ function from the Analsysis add-in.</p>
++ */
+ const long EXTERNAL = 3;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe the reference to a defined name (also known as named range)
++ used in formulas.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain an
++ integer value of type <atom>long</atom> specifying the index of the
++ defined name. This index can be obtained from the defined name using
++ its <type>NamedRange::TokenIndex</type> property.</p>
++
++ @see NamedRange
++ */
+ const long NAME = 4;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe an invalid name that resolves to the #NAME? error in formulas.
++
++ <p>The <member>FormulaToken::Data</member> member is not used
++ and should be empty.</p>
++ */
+ const long NO_NAME = 5;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe an empty function parameter.
++
++ <p>Example: In the formula =SUM(1;;2) the second parameter is empty
++ and represented by a formula token containing the "empty" op-code.</p>
++
++ <p>The <member>FormulaToken::Data</member> member is not used
++ and should be empty.</p>
++ */
+ const long MISSING = 6;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe "bad" data in a formula, e.g. data the formula parser was not
++ able to parse.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain a
++ <atom>string</string> with the bad data. This string will be displayed
++ in the formula.</p>
++ */
+ const long BAD = 7;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe white-space characters within the string representation of a
++ formula.
++
++ <p>White-space characters in formulas are used for readability and do
++ not affect the result of the formula.</p>
++
++ <p>The <member>FormulaToken::Data</member> member shall contain a
++ positive integer value of type <atom>long</atom> specifying the number
++ of space characters.</p>
++
++ <p>Attention: This may change in next versions to support other
++ characters than simple space characters (e.g. line feeds, horizontal
++ tabulators, non-breakable spaces).</p>
++ */
+ const long SPACES = 8;
++
++ // -----------------------------------------------------------------------
++
+ const long MAT_REF = 9;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe the reference to a database range used in formulas.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain an
++ integer value of type <atom>long</atom> specifying the index of the
++ database range. This index can be obtained from the database range
++ using its <type>DatabaseRange::TokenIndex</type> property.</p>
++
++ @see DatabaseRange
++ */
+ const long DB_AREA = 10;
++
++ // -----------------------------------------------------------------------
++
++ /** Formula tokens containing the op-code obtained from this offset
++ describe the reference to a macro function called in a formula.
++
++ <p>The <member>FormulaToken::Data</member> member shall contain a
++ <atom>string</atom> specifying the name of the macro function.</p>
++ */
const long MACRO = 11;
++
++ // -----------------------------------------------------------------------
++
const long COL_ROW_NAME = 12;
- const long COL_ROW_NAME_AUTO = 13;
-+ /// @since OOo 3.1
-+ const long EXTERNAL_REFERENCE = 14;
+- const long COL_ROW_NAME_AUTO = 13;
++
++ // -----------------------------------------------------------------------
++
};
- //=============================================================================
+-//=============================================================================
++// ===========================================================================
+
+ }; }; }; };
+
+diff --git offapi/com/sun/star/sheet/FormulaToken.idl offapi/com/sun/star/sheet/FormulaToken.idl
+index cec2ea4..c0aff64 100644
+--- offapi/com/sun/star/sheet/FormulaToken.idl
++++ offapi/com/sun/star/sheet/FormulaToken.idl
+@@ -44,6 +44,8 @@ struct FormulaToken
+ //-------------------------------------------------------------------------
+
+ /** is the OpCode of the token.
++
++ @see com::sun::star::sheet::XFormulaOpCodeMapper
+ */
+ long OpCode;
+
+diff --git offapi/com/sun/star/sheet/NamedRange.idl offapi/com/sun/star/sheet/NamedRange.idl
+index 30af011..c4d79dc 100644
+--- offapi/com/sun/star/sheet/NamedRange.idl
++++ offapi/com/sun/star/sheet/NamedRange.idl
+@@ -77,8 +77,9 @@ published service NamedRange
+
+ /** returns the index used to refer to this name in token arrays.
+
+- <p>A token describing a defined name shall contain the op-code
+- OPCODE_NAME and this index as data part.</p>
++ <p>A token describing a defined name shall contain the op-code obtained
++ from the <const>FormulaMapGroupSpecialOffset::NAME</const> offset and
++ this index as data part.</p>
+
+ @see com::sun::star::sheet::FormulaToken
+ @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::NAME
diff --git offapi/com/sun/star/sheet/XExternalDocLink.idl offapi/com/sun/star/sheet/XExternalDocLink.idl
new file mode 100644
-index 0000000..0f3e02b
+index 0000000..27a706c
--- /dev/null
+++ offapi/com/sun/star/sheet/XExternalDocLink.idl
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,94 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -491,6 +738,9 @@
+#ifndef __com_sun_star_sheet_XExternalDocLink_idl__
+#define __com_sun_star_sheet_XExternalDocLink_idl__
+
++#include <com/sun/star/container/XEnumerationAccess.idl>
++#include <com/sun/star/container/XIndexAccess.idl>
++#include <com/sun/star/container/XNameAccess.idl>
+#include <com/sun/star/sheet/XExternalSheetCache.idl>
+
+module com { module sun { module star { module sheet {
@@ -505,6 +755,10 @@
+ */
+interface XExternalDocLink
+{
++ interface com::sun::star::container::XNameAccess;
++ interface com::sun::star::container::XIndexAccess;
++ interface com::sun::star::container::XEnumerationAccess;
++
+ //-------------------------------------------------------------------------
+
+ /** <p>This method adds a new sheet cache instance to the extternal document
@@ -526,13 +780,16 @@
+
+ <p>This index value corresponds with the external document
+ represented by an instance of
-+ <type scope="com::sun::star::sheet">ExternalDocLink</type>. This
++ <type scope="com::sun::star::sheet">ExternalDocLink</type>. This
+ value is stored within a formula token instance.</p>
-+
-+ <p>Each external document link has a unique index value.</p>
+
++ <p>Each external document cache instance has a unique index value, and this
++ index value can be used to retrieve the corresponding external document cache
++ from the parent <type scope="com::sun::star::sheet">ExternalDocLinks</type> instance.</p>
++
++ @see com::sun::star::sheet::ExternalDocLinks
+ @see com::sun::star::sheet::FormulaToken
-+ @see com::sun::star::sheet::FormulaMapGroupSpecialOffset::EXTERNAL_REFERENCE
++ @see com::sun::star::sheet::ExternalReference
+ */
+ [attribute, readonly] long TokenIndex;
+};
@@ -616,10 +873,10 @@
+#endif
diff --git offapi/com/sun/star/sheet/XExternalSheetCache.idl offapi/com/sun/star/sheet/XExternalSheetCache.idl
new file mode 100644
-index 0000000..0c35f7f
+index 0000000..1d91f70
--- /dev/null
+++ offapi/com/sun/star/sheet/XExternalSheetCache.idl
-@@ -0,0 +1,84 @@
+@@ -0,0 +1,102 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -658,7 +915,7 @@
+module com { module sun { module star { module sheet {
+
+/** Primary interface for the <type scope="com::sun::star::sheet">ExternalSheetCache</type> service.
-+
++
+ @see com::sun::star::sheet::ExternalSheetCache
+
+ @since OOo 3.1.0
@@ -673,15 +930,15 @@
+ @param nColumn column position (0-based)
+ @param aValue cell value to be cached
+ */
-+ void setCellValue( [in] long nRow, [in] long nColumn, [in] any aValue )
++ void setCellValue( [in] long nColumn, [in] long nRow, [in] any aValue )
+ raises (com::sun::star::lang::IllegalArgumentException);
+
+ /** It retrieves a cached value from a specified cell position. The cached
+ value can be either <type>string</type> or <type>double</type>.
-+
++
+ @return any cached cell value
+ */
-+ any getCellValue( [in] long nRow, [in] long nColumn )
++ any getCellValue( [in] long nColumn, [in] long nRow )
+ raises (com::sun::star::lang::IllegalArgumentException);
+
+ /** It returns a list of all row numbers where a cached cell or cells exist.
@@ -691,14 +948,32 @@
+ */
+ sequence< long > getAllRows();
+
-+ /** Given a row number, this method returns a list of all columns numbers
-+ that store cached cell values in that row. The column numbers are
++ /** Given a row number, this method returns a list of all columns numbers
++ that store cached cell values in that row. The column numbers are
+ sorted in ascending order.
+
+ @return sequence<long> list of all columns numbers with cached cell values
+ */
+ sequence< long > getAllColumns( [in] long nRow )
+ raises (com::sun::star::lang::IllegalArgumentException);
++
++ //-------------------------------------------------------------------------
++
++ /** Index corresponding to this instance of an external sheet cache for
++ usage in formula tokens.
++
++ <p>This index to the external sheet cache is expected in the
++ <member>SingleReference::Sheet</member> member if it is part of an
++ external reference token.
++
++ <p>Each external sheet cache has a unique index value inside the
++ <type>ExternalDocLink</type> instance.</p>
++
++ @see FormulaToken
++ @see ExternalReference
++ */
++ [attribute, readonly] long TokenIndex;
++
+};
+
+}; }; }; };
Added: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-officecfg.diff Thu Jan 15 02:44:24 2009
@@ -0,0 +1,20 @@
+diff --git officecfg/registry/schema/org/openoffice/Office/Calc.xcs officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+index 7e55cf3..39e4950 100644
+--- officecfg/registry/schema/org/openoffice/Office/Calc.xcs
++++ officecfg/registry/schema/org/openoffice/Office/Calc.xcs
+@@ -785,13 +785,13 @@
+ <desc>MAX</desc>
+ </info>
+ </enumeration>
+- <enumeration oor:value="5">
++ <enumeration oor:value="6">
+ <info>
+ <desc>IF</desc>
+ </info>
+ </enumeration>
+ </constraints>
+- <value>224 226 222 223 5</value>
++ <value>224 226 222 223 6</value>
+ </prop>
+ <prop oor:name="AutoInput" oor:type="xs:boolean">
+ <!-- OldPath: Calc/Input -->
Modified: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff
==============================================================================
--- branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff (original)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-sc.diff Thu Jan 15 02:44:24 2009
@@ -251,7 +251,7 @@
BOOL IsCorrected() { return bCorrected; }
diff --git sc/inc/document.hxx sc/inc/document.hxx
-index a01f09b..5d4ca1f 100644
+index 2a27407..414f0c5 100644
--- sc/inc/document.hxx
+++ sc/inc/document.hxx
@@ -93,6 +93,7 @@ class ScDocProtection;
@@ -289,10 +289,10 @@
diff --git sc/inc/externalrefmgr.hxx sc/inc/externalrefmgr.hxx
new file mode 100644
-index 0000000..91be428
+index 0000000..fa2bd9e
--- /dev/null
+++ sc/inc/externalrefmgr.hxx
-@@ -0,0 +1,405 @@
+@@ -0,0 +1,524 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -332,12 +332,14 @@
+#include "sfx2/lnkbase.hxx"
+#include "tools/time.hxx"
+#include "vcl/timer.hxx"
++#include "svtools/zforlist.hxx"
+#include "scmatrix.hxx"
+
+#include <hash_map>
+#include <hash_set>
+#include <boost/shared_ptr.hpp>
+#include <vector>
++#include <list>
+
+class ScDocument;
+class ScToken;
@@ -375,38 +377,54 @@
+
+// ============================================================================
+
-+/**
++/**
+ * Cache table for external reference data.
+ */
+class ScExternalRefCache
+{
-+ struct RangeHash
-+ {
-+ size_t operator()(const ScRange& rRange) const
-+ {
-+ const ScAddress& s = rRange.aStart;
-+ const ScAddress& e = rRange.aEnd;
-+ return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row();
-+ }
-+ };
-+
+public:
-+
+ typedef ::boost::shared_ptr<ScToken> TokenRef;
+ typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
-+ typedef ::std::hash_map<SCCOL, TokenRef> RowDataType;
++
++ struct TableName
++ {
++ String maUpperName;
++ String maRealName;
++
++ explicit TableName(const String& rUppper, const String& rReal);
++ };
++
++ struct CellFormat
++ {
++ bool mbIsSet;
++ short mnType;
++ sal_uInt32 mnIndex;
++
++ explicit CellFormat();
++ };
++
++private:
++ /** individual cell within cached external ref table. */
++ struct Cell
++ {
++ TokenRef mxToken;
++ sal_uInt32 mnFmtIndex;
++ };
++ typedef ::std::hash_map<SCCOL, Cell> RowDataType;
+ typedef ::std::hash_map<SCROW, RowDataType> RowsDataType;
+
++public:
+ class Table
+ {
+ public:
+ Table();
+ ~Table();
+
-+ void setCell(SCROW nRow, SCCOL nCol, TokenRef pToken);
-+ TokenRef getCell(SCROW nRow, SCCOL nCol) const;
++ void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0);
++ TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const;
+ void getAllRows(::std::vector<SCROW>& rRows) const;
+ void getAllCols(SCROW nRow, ::std::vector<SCCOL>& rCols) const;
++ void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
+
+ private:
+ RowsDataType maRows;
@@ -421,24 +439,26 @@
+ const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const;
+ const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
+
-+ /**
++ /**
+ * Get a cached cell data at specified cell location.
+ *
+ * @param nFileId file ID of an external document
+ * @param rTabName sheet name
-+ * @param nRow
-+ * @param nCol
-+ *
++ * @param nRow
++ * @param nCol
++ *
+ * @return pointer to the token instance in the cache. <i>The caller does
+ * not need to delete this instance since its life cycle is
+ * managed by this class.</i>
+ */
-+ ScExternalRefCache::TokenRef getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol);
++ ScExternalRefCache::TokenRef getCellData(
++ sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol,
++ sal_uInt32* pnFmtIndex = NULL);
+
-+ /**
-+ * Get a cached cell range data.
-+ *
-+ * @return a new token array instance. Note that <i>the caller must
++ /**
++ * Get a cached cell range data.
++ *
++ * @return a new token array instance. Note that <i>the caller must
+ * manage the life cycle of the returned instance</i>, which is
+ * guaranteed if the TokenArrayRef is properly used..
+ */
@@ -447,7 +467,7 @@
+ ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName);
+ void setRangeNameTokens(sal_uInt16 nFileId, const String& rName, TokenArrayRef pArray);
+
-+ void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken);
++ void setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken, sal_uInt32 nFmtIndex);
+
+ struct SingleRangeData
+ {
@@ -460,40 +480,32 @@
+
+ bool isDocInitialized(sal_uInt16 nFileId);
+ void initializeDoc(sal_uInt16 nFileId, const ::std::vector<String>& rTabNames);
++ String getTableName(sal_uInt16 nFileId, size_t nCacheId) const;
+ void getAllTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
++ void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
++ bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const;
++ size_t getCacheTableCount(sal_uInt16 nFileId) const;
+
-+ /**
-+ * Get a cache table instance for specified file and table name. If the
-+ * table instance is not already present, it'll instantiate a new one and
-+ * append it to the end of the table array. <I>It's important to be
-+ * aware of this fact especially for multi-table ranges for which
-+ * table orders are critical.</I>
-+ *
-+ * Excel filter calls this method to populate the cache table from the
-+ * XCT/CRN records.
-+ *
-+ * @param nFileId file ID
-+ * @param rTabName table name
-+ *
-+ * @return shared_ptr to the cache table instance
-+ */
-+ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew);
++ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
++ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex);
+
+ void clearCache(sal_uInt16 nFileId);
+
+private:
++ struct RangeHash
++ {
++ size_t operator()(const ScRange& rRange) const
++ {
++ const ScAddress& s = rRange.aStart;
++ const ScAddress& e = rRange.aEnd;
++ return s.Tab() + s.Col() + s.Row() + e.Tab() + e.Col() + e.Row();
++ }
++ };
++
+ typedef ::std::hash_map<String, TokenArrayRef, ScStringHashCode> RangeNameMap;
+ typedef ::std::hash_map<ScRange, TokenArrayRef, RangeHash> RangeArrayMap;
+ typedef ::std::hash_map<String, String, ScStringHashCode> NamePairMap;
+
-+ struct TableName
-+ {
-+ String maUpperName;
-+ String maRealName;
-+
-+ explicit TableName(const String& rUppper, const String& rReal);
-+ };
-+
+ /** Represents data cached for a single external document. */
+ struct DocItem
+ {
@@ -525,16 +537,50 @@
+
+class ScExternalRefManager
+{
-+private:
-+ struct AddressHash
++public:
++ /**
++ * Collection of cell addresses that contain external references. This
++ * data is used for link updates.
++ */
++ class RefCells
+ {
-+ size_t operator()(const ScAddress& rAddr) const
-+ {
-+ // dumb hashing - how do we properly hash a cell address?
-+ return rAddr.Tab() + rAddr.Col() + rAddr.Row();
-+ }
++ public:
++ RefCells();
++ ~RefCells();
++
++ void insertCell(const ScAddress& rAddr);
++ void removeCell(const ScAddress& rAddr);
++ void moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
++ void insertTable(SCTAB nPos);
++ void removeTable(SCTAB nPos);
++ void refreshAllCells(ScExternalRefManager& rRefMgr);
++ private:
++
++ typedef ::std::hash_set<SCROW> RowSet;
++ typedef ::std::hash_map<SCCOL, RowSet> ColSet;
++ struct TabItem
++ {
++ SCTAB mnIndex;
++ ColSet maCols;
++ explicit TabItem(SCTAB nIndex);
++ explicit TabItem(const TabItem& r);
++ };
++ typedef ::boost::shared_ptr<TabItem> TabItemRef;
++
++ /**
++ * Return the position that points either to the specified table
++ * position or to the position where a new table would be inserted in
++ * case the specified table is not present.
++ *
++ * @param nTab index of the desired table
++ */
++ ::std::list<TabItemRef>::iterator getTabPos(SCTAB nTab);
++
++ // This list must be sorted by the table index at all times.
++ ::std::list<TabItemRef> maTables;
+ };
+
++private:
+ /** Shell instance for a source document. */
+ struct SrcShell
+ {
@@ -542,14 +588,11 @@
+ Time maLastAccess;
+ };
+
-+ typedef ::boost::shared_ptr<ScToken> TokenRef;
-+ typedef ::boost::shared_ptr<ScTokenArray> TokenArrayRef;
-+
-+ typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap;
-+ typedef ::std::hash_set<sal_uInt16> LinkedDocSet;
++ typedef ::std::hash_map<sal_uInt16, SrcShell> DocShellMap;
++ typedef ::std::hash_set<sal_uInt16> LinkedDocSet;
+
-+ typedef ::std::hash_set<ScAddress, AddressHash, ::std::equal_to<ScAddress> > RefCellSet;
-+ typedef ::std::hash_map<sal_uInt16, RefCellSet> RefCellMap;
++ typedef ::std::hash_map<sal_uInt16, RefCells> RefCellMap;
++ typedef ::std::hash_map<sal_uInt16, SvNumberFormatterMergeMap> NumFmtMap;
+
+public:
+ /** Source document meta-data container. */
@@ -565,35 +608,80 @@
+ explicit ScExternalRefManager(ScDocument* pDoc);
+ ~ScExternalRefManager();
+
-+ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew = true);
-+ void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray);
++ String getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const;
++
++ /**
++ * Get a cache table instance for specified table and table index. Unlike
++ * the other method that takes a table name, this method does not create a
++ * new table when a table is not available for specified index.
++ *
++ * @param nFileId file ID
++ * @param nTabIndex cache table index
++ *
++ * @return shared_ptr to the cache table instance
++ */
++ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const;
+
-+ ScExternalRefCache::TokenRef getSingleRefToken(sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell, const ScAddress* pCurPos, SCTAB* pTab);
++ /**
++ * Get a cache table instance for specified file and table name. If the
++ * table instance is not already present, it'll instantiate a new one and
++ * append it to the end of the table array. <I>It's important to be
++ * aware of this fact especially for multi-table ranges for which
++ * table orders are critical.</I>
++ *
++ * Excel filter calls this method to populate the cache table from the
++ * XCT/CRN records.
++ *
++ * @param nFileId file ID
++ * @param rTabName table name
++ *
++ * @return shared_ptr to the cache table instance
++ */
++ ScExternalRefCache::TableTypeRef getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex = 0);
++ void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
+
+ /**
-+ * Get an array of tokens that consist of the specified external cell
-+ * range.
++ * Get all unique number format indices that are used in the cache tables.
++ * The retrieved indices are sorted in ascending order.
++ *
++ * @param rNumFmts (reference) all unique number format indices.
++ */
++ void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const;
++
++ bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const;
++ size_t getCacheTableCount(sal_uInt16 nFileId) const;
++ sal_uInt16 getExternalFileCount() const;
++
++ void storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray);
++
++ ScExternalRefCache::TokenRef getSingleRefToken(
++ sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
++ const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt = NULL);
++
++ /**
++ * Get an array of tokens that consist of the specified external cell
++ * range.
+ *
+ * @param nFileId file ID for an external document
+ * @param rTabName referenced sheet name
+ * @param rRange referenced cell range
-+ * @param pCurPos current cursor position to keep track of cells that
++ * @param pCurPos current cursor position to keep track of cells that
+ * reference an external data.
-+ *
-+ * @return shared_ptr to a token array instance. <i>The caller must not
++ *
++ * @return shared_ptr to a token array instance. <i>The caller must not
+ * delete the instance returned by this method.</i>
+ */
+ ScExternalRefCache::TokenArrayRef getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos);
+
-+ /**
-+ * Get an array of tokens corresponding with a specified name in a
-+ * specified file.
-+ *
-+ * @param pCurPos currnet cell address where this name token is used.
++ /**
++ * Get an array of tokens corresponding with a specified name in a
++ * specified file.
++ *
++ * @param pCurPos currnet cell address where this name token is used.
+ * This is purely to keep track of all cells containing
+ * external names for refreshing purposes. If this is
+ * NULL, then the cell will not be added to the list.
-+ *
++ *
+ * @return shared_ptr to array of tokens composing the name
+ */
+ ScExternalRefCache::TokenArrayRef getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos = NULL);
@@ -601,34 +689,33 @@
+ const String& getOwnDocumentName() const;
+ bool isOwnDocument(const String& rFile) const;
+
-+ /**
-+ * Takes a flat file name, and convert it to an absolute URL path. An
-+ * absolute URL path begines with 'file:///.
++ /**
++ * Takes a flat file name, and convert it to an absolute URL path. An
++ * absolute URL path begines with 'file:///.
+ *
-+ * @param rFile file name to convert
++ * @param rFile file name to convert
+ */
+ void convertToAbsName(String& rFile) const;
+ sal_uInt16 getExternalFileId(const String& rFile);
+ const String* getExternalFileName(sal_uInt16 nFileId) const;
++ bool hasExternalFile(sal_uInt16 nFileId) const;
++ bool hasExternalFile(const String& rFile) const;
+ const SrcFileData* getExternalFileData(sal_uInt16 nFileId) const;
+
+ const String* getRealTableName(sal_uInt16 nFileId, const String& rTabName) const;
+ const String* getRealRangeName(sal_uInt16 nFileId, const String& rRangeName) const;
-+ void getAllCachedTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const;
-+ sal_uInt16 getCachedFileCount() const;
+ void refreshNames(sal_uInt16 nFileId);
+ void switchSrcFile(sal_uInt16 nFileId, const String& rNewFile);
+
+ void setRelativeFileName(sal_uInt16 nFileId, const String& rRelUrl);
+
-+ /**
-+ * Set the filter name and options if any for a given source document.
-+ * These values get reset when the source document ever gets reloaded.
++ /**
++ * Set the filter name and options if any for a given source document.
++ * These values get reset when the source document ever gets reloaded.
+ *
-+ * @param nFileId
-+ * @param rFilterName
-+ * @param rOptions
-+ * @return
++ * @param nFileId
++ * @param rFilterName
++ * @param rOptions
+ */
+ void setFilterData(sal_uInt16 nFileId, const String& rFilterName, const String& rOptions);
+
@@ -637,20 +724,48 @@
+
+ bool hasExternalData() const;
+
-+ /**
-+ * Re-generates relative names for all stored source files. This is
-+ * necessary when exporting to an ods document, to ensure that all source
++ /**
++ * 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.
+ */
+ void resetSrcFileData();
+
++ /**
++ * Update a single referencing cell position.
++ *
++ * @param rOldPos old position
++ * @param rNewPos new position
++ */
++ void updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy);
++
++ /**
++ * Update referencing cells affected by sheet movement.
++ *
++ * @param nOldTab old sheet position
++ * @param nNewTab new sheet position
++ * @param bCopy whether this is a sheet move (false) or sheet copy (true)
++ */
++ void updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy);
++
++ /**
++ * Update referencing cells affected by sheet insertion.
++ *
++ * @param nPos sheet insertion position. All sheets to the right
++ * including the one at the insertion poistion shift to the
++ * right by one.
++ */
++ void updateRefInsertTable(SCTAB nPos);
++
++ void updateRefDeleteTable(SCTAB nPos);
++
+private:
+ ScExternalRefManager();
-+ ScExternalRefManager(const ScExternalRefManager&);
++ ScExternalRefManager(const ScExternalRefManager&);
+
-+ void refreshAllReferencingCells(sal_uInt16 nFileId);
++ void refreshAllRefCells(sal_uInt16 nFileId);
+
-+ void insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell);
++ void insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell);
+
+ ScDocument* getSrcDocument(sal_uInt16 nFileId);
+ SfxObjectShellRef loadSrcDocument(sal_uInt16 nFileId, String& rFilter);
@@ -660,22 +775,24 @@
+
+ bool compileTokensByCell(const ScAddress& rCell);
+
-+ /**
-+ * Purge those source document instances that have not been accessed for
++ /**
++ * Purge those source document instances that have not been accessed for
+ * the specified duration.
-+ *
-+ * @param nTimeOut time out value in 100th of a second
++ *
++ * @param nTimeOut time out value in 100th of a second
+ */
+ void purgeStaleSrcDocument(sal_Int32 nTimeOut);
+
++ sal_uInt32 getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc);
++
+private:
+ /** cache of referenced ranges and names from source documents. */
+ ScExternalRefCache maRefCache;
+
+ ScDocument* mpDoc;
+
-+ /**
-+ * Source document cache. This stores the original source document shell
++ /**
++ * Source document cache. This stores the original source document shell
+ * instances. They get purged after a certain period of time.
+ */
+ DocShellMap maDocShells;
@@ -683,12 +800,14 @@
+ /** list of source documents that are managed by the link manager. */
+ LinkedDocSet maLinkedDocs;
+
-+ /**
++ /**
+ * List of referencing cells that may contain external names. There is
+ * one list per source document.
+ */
+ RefCellMap maRefCells;
+
++ NumFmtMap maNumFormatMap;
++
+ /** original source file index. */
+ ::std::vector<SrcFileData> maSrcFiles;
+
@@ -699,7 +818,7 @@
+
+#endif
diff --git sc/inc/linkuno.hxx sc/inc/linkuno.hxx
-index b6fc524..586986e 100644
+index b6fc524..6dd39e8 100644
--- sc/inc/linkuno.hxx
+++ sc/inc/linkuno.hxx
@@ -36,6 +36,9 @@
@@ -728,7 +847,7 @@
class ScAreaLink;
class ScDocShell;
-@@ -493,8 +501,112 @@ public:
+@@ -493,8 +501,137 @@ public:
throw(::com::sun::star::uno::RuntimeException);
};
@@ -737,15 +856,15 @@
+class ScExternalSheetCacheObj : public cppu::WeakImplHelper1< ::com::sun::star::sheet::XExternalSheetCache >
+{
+public:
-+ explicit ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable);
++ explicit ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex);
+ ~ScExternalSheetCacheObj();
+
+ // XExternalSheetCache
+ virtual void SAL_CALL setCellValue(
-+ sal_Int32 nRow, sal_Int32 nCol, const ::com::sun::star::uno::Any& rAny)
++ sal_Int32 nCol, sal_Int32 nRow, const ::com::sun::star::uno::Any& rAny)
+ throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+
-+ virtual ::com::sun::star::uno::Any SAL_CALL getCellValue(sal_Int32 nRow, sal_Int32 nCol)
++ virtual ::com::sun::star::uno::Any SAL_CALL getCellValue(sal_Int32 nCol, sal_Int32 nRow)
+ throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL getAllRows()
@@ -754,16 +873,21 @@
+ virtual ::com::sun::star::uno::Sequence< sal_Int32 > SAL_CALL getAllColumns(sal_Int32 nRow)
+ throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+
++ // Attributes
++ virtual sal_Int32 SAL_CALL getTokenIndex()
++ throw (::com::sun::star::uno::RuntimeException);
++
+private:
+ ScExternalSheetCacheObj();
+ ScExternalSheetCacheObj(const ScExternalSheetCacheObj&);
+
+private:
+ ScExternalRefCache::TableTypeRef mpTable;
++ size_t mnIndex;
+};
-+
+
+// ============================================================================
-+
+
+class ScExternalDocLinkObj : public cppu::WeakImplHelper1< ::com::sun::star::sheet::XExternalDocLink >
+{
+public:
@@ -771,10 +895,36 @@
+ ~ScExternalDocLinkObj();
+
+ // XExternalDocLink
-+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalSheetCache >
-+ SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName )
++ virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalSheetCache >
++ SAL_CALL addSheetCache( const ::rtl::OUString& aSheetName )
+ throw (::com::sun::star::uno::RuntimeException);
+
++ // XNameAccess
++ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
++ throw(::com::sun::star::container::NoSuchElementException,
++ ::com::sun::star::lang::WrappedTargetException,
++ ::com::sun::star::uno::RuntimeException);
++ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
++ throw(::com::sun::star::uno::RuntimeException);
++ virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
++ throw(::com::sun::star::uno::RuntimeException);
++
++ // XIndexAccess
++ virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
++ virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
++ throw(::com::sun::star::lang::IndexOutOfBoundsException,
++ ::com::sun::star::lang::WrappedTargetException,
++ ::com::sun::star::uno::RuntimeException);
++
++ // XEnumerationAccess
++ virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
++ createEnumeration() throw(::com::sun::star::uno::RuntimeException);
++
++ // XElementAccess
++ virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
++ throw(::com::sun::star::uno::RuntimeException);
++ virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
++
+ // Attributes
+ virtual sal_Int32 SAL_CALL getTokenIndex()
+ throw (::com::sun::star::uno::RuntimeException);
@@ -794,47 +944,41 @@
+ ~ScExternalDocLinksObj();
+
+ // XExternalDocLinks
-+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink >
-+ SAL_CALL addDocLink( const ::rtl::OUString& aDocName )
++ virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink >
++ SAL_CALL addDocLink( const ::rtl::OUString& aDocName )
+ throw (::com::sun::star::uno::RuntimeException);
-
-+ // XNameAccess
-+ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
-+ throw(::com::sun::star::container::NoSuchElementException,
-+ ::com::sun::star::lang::WrappedTargetException,
-+ ::com::sun::star::uno::RuntimeException);
-+ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
-+ throw(::com::sun::star::uno::RuntimeException);
-+ virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
-+ throw(::com::sun::star::uno::RuntimeException);
-+
-+ // XIndexAccess
-+ virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
-+ virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
-+ throw(::com::sun::star::lang::IndexOutOfBoundsException,
-+ ::com::sun::star::lang::WrappedTargetException,
-+ ::com::sun::star::uno::RuntimeException);
-+
-+ // XEnumerationAccess
-+ virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
-+ createEnumeration() throw(::com::sun::star::uno::RuntimeException);
-+
-+ // XElementAccess
-+ virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
-+ throw(::com::sun::star::uno::RuntimeException);
-+ virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
-
++
++ // XNameAccess
++ virtual ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName )
++ throw(::com::sun::star::container::NoSuchElementException,
++ ::com::sun::star::lang::WrappedTargetException,
++ ::com::sun::star::uno::RuntimeException);
++ virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames()
++ throw(::com::sun::star::uno::RuntimeException);
++ virtual sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName )
++ throw(::com::sun::star::uno::RuntimeException);
++
++ // XIndexAccess
++ virtual sal_Int32 SAL_CALL getCount() throw(::com::sun::star::uno::RuntimeException);
++ virtual ::com::sun::star::uno::Any SAL_CALL getByIndex( sal_Int32 nIndex )
++ throw(::com::sun::star::lang::IndexOutOfBoundsException,
++ ::com::sun::star::lang::WrappedTargetException,
++ ::com::sun::star::uno::RuntimeException);
++
++ // XEnumerationAccess
++ virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL
++ createEnumeration() throw(::com::sun::star::uno::RuntimeException);
++
++ // XElementAccess
++ virtual ::com::sun::star::uno::Type SAL_CALL getElementType()
++ throw(::com::sun::star::uno::RuntimeException);
++ virtual sal_Bool SAL_CALL hasElements() throw(::com::sun::star::uno::RuntimeException);
++
+private:
+ ScExternalDocLinksObj();
+ ScExternalDocLinksObj(const ScExternalDocLinksObj&);
+
+private:
-+ typedef ::std::hash_map<
-+ ::rtl::OUString,
-+ ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XExternalDocLink >,
-+ ::rtl::OUStringHash > DocLinkMap;
-+ DocLinkMap maDocLinks;
-+ ::std::vector< ::rtl::OUString > maDocNames;
+ ScDocShell* mpDocShell;
+ ScExternalRefManager* mpRefMgr;
+};
@@ -865,6 +1009,28 @@
};
inline void SingleRefData::InitAddress( SCCOL nColP, SCROW nRowP, SCTAB nTabP )
+diff --git sc/inc/scmatrix.hxx sc/inc/scmatrix.hxx
+index dbe8bc7..0f2fcb1 100644
+--- sc/inc/scmatrix.hxx
++++ sc/inc/scmatrix.hxx
+@@ -115,11 +115,14 @@ class ScMatrix
+
+ public:
+
+- /// The maximum number of elements a matrix may have at runtime
++ /// The maximum number of elements a matrix may have at runtime.
+ inline static size_t GetElementsMax()
+ {
+- const size_t nMemMax = (((size_t)(~0))-64) / sizeof(ScMatrixValue);
+- const size_t nArbitraryLimit = 0x80000; // 512k elements ~= 4MB memory
++ // Roughly 125MB in total, divided by 8+1 per element => 14M elements.
++ const size_t nMemMax = 0x08000000 / (sizeof(ScMatrixValue) + sizeof(ScMatValType));
++ // With MAXROWCOUNT==65536 and 128 columns => 8M elements ~72MB.
++ const size_t nArbitraryLimit = (size_t)MAXROWCOUNT * 128;
++ // Stuffed with a million rows would limit this to 14 columns.
+ return nMemMax < nArbitraryLimit ? nMemMax : nArbitraryLimit;
+ }
+
diff --git sc/inc/token.hxx sc/inc/token.hxx
index ded3a94..bc7e993 100644
--- sc/inc/token.hxx
@@ -965,7 +1131,7 @@
/** Xcl import may play dirty tricks with OpCode!=ocExternal.
Others don't use! */
diff --git sc/inc/tokenuno.hxx sc/inc/tokenuno.hxx
-index a03b6ec..5db0e32 100644
+index a03b6ec..f12b484 100644
--- sc/inc/tokenuno.hxx
+++ sc/inc/tokenuno.hxx
@@ -38,9 +38,8 @@
@@ -979,7 +1145,19 @@
#include <cppuhelper/implbase3.hxx>
#include <cppuhelper/implbase2.hxx>
#include "address.hxx"
-@@ -70,6 +69,7 @@ class ScFormulaParserObj : public ::cppu::WeakImplHelper3<
+@@ -54,9 +53,11 @@ class ScTokenConversion
+ {
+ public:
+ static bool ConvertToTokenArray(
++ ScDocument& rDoc,
+ ScTokenArray& rTokenArray,
+ const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& rSequence );
+ static bool ConvertToTokenSequence(
++ ScDocument& rDoc,
+ com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& rSequence,
+ const ScTokenArray& rTokenArray );
+ };
+@@ -70,6 +71,7 @@ class ScFormulaParserObj : public ::cppu::WeakImplHelper3<
{
private:
::com::sun::star::uno::Sequence< const ::com::sun::star::sheet::FormulaOpCodeMapEntry > maOpCodeMapping;
@@ -988,7 +1166,7 @@
ScDocShell* mpDocShell;
ScAddress maRefPos;
diff --git sc/inc/unonames.hxx sc/inc/unonames.hxx
-index b2c45ac..18c858b 100644
+index 8bc928b..3573c7d 100644
--- sc/inc/unonames.hxx
+++ sc/inc/unonames.hxx
@@ -47,6 +47,7 @@
@@ -1025,8 +1203,38 @@
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( t->GetIndex() );
if( pRangeData )
+diff --git sc/source/core/data/cell2.cxx sc/source/core/data/cell2.cxx
+index fc6df5f..657ebb8 100644
+--- sc/source/core/data/cell2.cxx
++++ sc/source/core/data/cell2.cxx
+@@ -51,6 +51,7 @@
+ #include "indexmap.hxx"
+ #include "scitems.hxx"
+ #include "patattr.hxx"
++#include "externalrefmgr.hxx"
+
+ // STATIC DATA -----------------------------------------------------------
+
+@@ -904,6 +905,17 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode,
+
+ delete pOld;
+ }
++
++ pCode->Reset();
++ for ( ScToken* t = pCode->GetNextReferenceOrName(); t; t = pCode->GetNextReferenceOrName() )
++ {
++ StackVar sv = t->GetType();
++ if (sv == svExternalSingleRef || sv == svExternalDoubleRef || sv == svExternalName)
++ {
++ pDocument->GetExternalRefManager()->updateRefCell(aOldPos, aPos, eUpdateRefMode == URM_COPY);
++ break;
++ }
++ }
+ }
+
+ void ScFormulaCell::UpdateInsertTab(SCTAB nTable)
diff --git sc/source/core/data/documen2.cxx sc/source/core/data/documen2.cxx
-index b75279e..d739a17 100644
+index b75279e..825baf5 100644
--- sc/source/core/data/documen2.cxx
+++ sc/source/core/data/documen2.cxx
@@ -94,6 +94,7 @@
@@ -1057,6 +1265,28 @@
ScAddInAsync::RemoveDocument( this );
ScAddInListener::RemoveDocument( this );
delete pChartListenerCollection; // vor pBASM wg. evtl. Listener!
+@@ -1429,6 +1436,10 @@ BOOL ScDocument::MoveTab( SCTAB nOldPos, SCTAB nNewPos )
+ if (pDrawLayer)
+ DrawMovePage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
+
++ // Update cells containing external references.
++ if (pExternalRefMgr.get())
++ pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, false);
++
+ bValid = TRUE;
+ }
+ }
+@@ -1548,6 +1559,10 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM
+ DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) );
+
+ pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() );
++
++ // Update cells containing external references.
++ if (pExternalRefMgr.get())
++ pExternalRefMgr->updateRefMoveTable(nOldPos, nNewPos, true);
+ }
+ else
+ SetAutoCalc( bOldAutoCalc );
diff --git sc/source/core/data/documen3.cxx sc/source/core/data/documen3.cxx
index 541e2e4..20dae1e 100644
--- sc/source/core/data/documen3.cxx
@@ -1141,8 +1371,56 @@
void ScDocument::UpdateDdeLinks()
{
if (pLinkManager)
+diff --git sc/source/core/data/document.cxx sc/source/core/data/document.cxx
+index 886156d..705c73b 100644
+--- sc/source/core/data/document.cxx
++++ sc/source/core/data/document.cxx
+@@ -91,6 +91,7 @@
+ #include "bcaslot.hxx"
+ #include "postit.hxx"
+ #include "tabprotection.hxx"
++#include "externalrefmgr.hxx"
+
+ struct ScDefaultAttr
+ {
+@@ -368,6 +369,10 @@ BOOL ScDocument::InsertTab( SCTAB nPos, const String& rName,
+ if ( pChartListenerCollection )
+ pChartListenerCollection->UpdateScheduledSeriesRanges();
+
++ // Update cells containing external references.
++ if (pExternalRefMgr.get())
++ pExternalRefMgr->updateRefInsertTable(nPos);
++
+ SetDirty();
+ bValid = TRUE;
+ }
+@@ -457,6 +462,12 @@ BOOL ScDocument::DeleteTab( SCTAB nTab, ScDocument* pRefUndoDoc )
+ }
+ // #81844# sheet names of references are not valid until sheet is deleted
+ pChartListenerCollection->UpdateScheduledSeriesRanges();
++
++
++ // Update cells containing external references.
++ if (pExternalRefMgr.get())
++ pExternalRefMgr->updateRefDeleteTable(nTab);
++
+ SetAutoCalc( bOldAutoCalc );
+ bValid = TRUE;
+ }
+diff --git sc/source/core/inc/interpre.hxx sc/source/core/inc/interpre.hxx
+index b9dd766..2035004 100644
+--- sc/source/core/inc/interpre.hxx
++++ sc/source/core/inc/interpre.hxx
+@@ -505,6 +505,7 @@ BOOL SetSbxVariable( SbxVariable* pVar, SCCOL nCol, SCROW nRow, SCTAB nTab );
+ void ScErrorType();
+ void ScDBArea();
+ void ScColRowNameAuto();
++void ScExternalRef();
+ void ScGetPivotData();
+ void ScHyperLink();
+ void ScBahtText();
diff --git sc/source/core/tool/address.cxx sc/source/core/tool/address.cxx
-index 2cb5dce..4572ccd 100644
+index df51606..5b68bbc 100644
--- sc/source/core/tool/address.cxx
+++ sc/source/core/tool/address.cxx
@@ -35,12 +35,15 @@
@@ -1211,7 +1489,19 @@
static long int
sal_Unicode_strtol ( const sal_Unicode* p,
const sal_Unicode** pEnd )
-@@ -102,31 +148,18 @@ sal_Unicode_strtol ( const sal_Unicode* p,
+@@ -99,34 +145,30 @@ sal_Unicode_strtol ( const sal_Unicode* p,
+ return is_neg ? -accum : accum;
+ }
+
++const sal_Unicode* lcl_eatWhiteSpace( const sal_Unicode* p )
++{
++ if ( p )
++ {
++ while( *p == ' ' )
++ ++p;
++ }
++ return p;
++}
// Returns NULL if the string should be a sheet name, but is invalid
// Returns a pointer to the first character after the sheet name
static const sal_Unicode *
@@ -1246,7 +1536,7 @@
return NULL;
}
else
-@@ -190,26 +223,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
+@@ -190,26 +232,7 @@ lcl_XL_ParseSheetRef( const sal_Unicode *start,
aTabName.Append( start, sal::static_int_cast<xub_StrLen>( p - start ) );
}
@@ -1274,7 +1564,7 @@
return p;
}
-@@ -220,46 +234,71 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+@@ -220,46 +243,71 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
String& rExternDocName,
String& rStartTabName,
String& rEndTabName,
@@ -1283,7 +1573,7 @@
+ const uno::Sequence< const sheet::ExternalLinkInfo > * pExternalLinks )
{
const sal_Unicode* startTabs, *start = p;
-
+ USHORT nSaveFlags = nFlags;
// Is this an external reference ?
rStartTabName.Erase();
rEndTabName.Erase();
@@ -1366,16 +1656,30 @@
if( NULL == p )
return start; // invalid tab
if( p != startTabs )
-@@ -267,7 +306,7 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+@@ -267,9 +315,12 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
nFlags |= SCA_VALID_TAB | SCA_TAB_3D | SCA_TAB_ABSOLUTE;
if( *p == ':' ) // 3d ref
{
- p = lcl_XL_ParseSheetRef( p+1, &r.aEnd, pDoc, rExternDocName, rEndTabName, FALSE );
+ p = lcl_XL_ParseSheetRef( p+1, rEndTabName, FALSE );
if( p == NULL )
++ {
++ nFlags = nSaveFlags;
return start; // invalid tab
++ }
nFlags |= SCA_VALID_TAB2 | SCA_TAB2_3D | SCA_TAB2_ABSOLUTE;
-@@ -289,45 +328,36 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+ }
+ else
+@@ -288,6 +339,8 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
+ nFlags = nSaveFlags;
+ return start; // syntax error
+ }
++ else
++ p = lcl_eatWhiteSpace( p );
+ }
+ else
+ {
+@@ -295,45 +348,39 @@ lcl_ScRange_Parse_XL_Header( ScRange& r,
// Use the current tab, it needs to be passed in. : r.aEnd.SetTab( .. );
}
@@ -1399,7 +1703,10 @@
- pDoc->GetDocumentShell() );
+ // Internal reference.
+ if (!rStartTabName.Len())
++ {
++ nFlags = nSaveFlags;
+ return start;
++ }
- String aDocTab;
-
@@ -1444,7 +1751,7 @@
}
-@@ -427,7 +457,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -433,7 +480,8 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
const sal_Unicode* p,
ScDocument* pDoc,
const ScAddress::Details& rDetails,
@@ -1454,7 +1761,7 @@
{
const sal_Unicode* pTmp = NULL;
String aExternDocName, aStartTabName, aEndTabName;
-@@ -441,7 +472,19 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -447,7 +495,19 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
}
#endif
p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
@@ -1475,7 +1782,7 @@
if( NULL == p )
return 0;
-@@ -480,8 +523,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -486,8 +546,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetCol( 0 );
r.aEnd.SetCol( MAXCOL );
@@ -1485,7 +1792,7 @@
}
else if( NULL == (p = lcl_r1c1_get_col( p, rDetails, &r.aStart, &nFlags )))
goto failed;
-@@ -501,8 +543,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -507,8 +566,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
return nFlags;
}
@@ -1495,7 +1802,7 @@
}
p = pTmp;
-@@ -517,8 +558,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -523,8 +581,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
@@ -1505,7 +1812,7 @@
}
else if( *p == 'C' || *p == 'c' ) // full col C#
{
-@@ -550,8 +590,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
+@@ -556,8 +613,7 @@ lcl_ScRange_Parse_XL_R1C1( ScRange& r,
r.aStart.SetRow( 0 );
r.aEnd.SetRow( MAXROW );
@@ -1515,7 +1822,7 @@
}
failed :
-@@ -604,7 +643,9 @@ static USHORT
+@@ -610,7 +666,9 @@ static USHORT
lcl_ScRange_Parse_XL_A1( ScRange& r,
const sal_Unicode* p,
ScDocument* pDoc,
@@ -1526,7 +1833,7 @@
{
const sal_Unicode* tmp1, *tmp2;
String aExternDocName, aStartTabName, aEndTabName; // for external link table
-@@ -618,7 +659,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -629,7 +687,19 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
}
#endif
p = lcl_ScRange_Parse_XL_Header( r, p, pDoc,
@@ -1547,7 +1854,20 @@
if( NULL == p )
return 0;
-@@ -640,8 +693,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -640,8 +710,12 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+ return 0;
+
+ tmp1 = lcl_a1_get_row( p, &r.aStart, &nFlags );
++
++ tmp1 = lcl_eatWhiteSpace( tmp1 );
+ if( !tmp1 || *tmp1++ != ':' ) // Even a singleton requires ':' (eg 2:2)
+ return 0;
++
++ tmp1 = lcl_eatWhiteSpace( tmp1 );
+ tmp2 = lcl_a1_get_row( tmp1, &r.aEnd, &nFlags2 );
+ if( !tmp2 )
+ return 0;
+@@ -651,8 +725,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
SCA_VALID_COL | SCA_VALID_COL2 |
SCA_COL_ABSOLUTE | SCA_COL2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
@@ -1557,7 +1877,19 @@
}
tmp2 = lcl_a1_get_row( tmp1, &r.aStart, &nFlags );
-@@ -661,8 +713,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -661,8 +734,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+ if( bOnlyAcceptSingle ) // by definition full col refs are ranges
+ return 0;
+
++ tmp1 = lcl_eatWhiteSpace( tmp1 );
+ if( *tmp1++ != ':' ) // Even a singleton requires ':' (eg F:F)
+ return 0;
++
++ tmp1 = lcl_eatWhiteSpace( tmp1 );
+ tmp2 = lcl_a1_get_col( tmp1, &r.aEnd, &nFlags2 );
+ if( !tmp2 )
+ return 0;
+@@ -672,8 +748,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
SCA_VALID_ROW | SCA_VALID_ROW2 |
SCA_ROW_ABSOLUTE | SCA_ROW2_ABSOLUTE;
nFlags |= (nFlags2 << 4);
@@ -1567,7 +1899,7 @@
}
// prepare as if it's a singleton, in case we want to fall back */
-@@ -672,8 +723,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -683,8 +758,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
if ( bOnlyAcceptSingle )
{
if ( *tmp2 == 0 )
@@ -1577,9 +1909,21 @@
else
{
// any trailing invalid character must invalidate the address.
-@@ -692,12 +742,11 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -693,6 +767,7 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+ }
+ }
+
++ tmp2 = lcl_eatWhiteSpace( tmp2 );
+ if( *tmp2 != ':' )
+ {
+ nFlags &= ~(SCA_VALID | SCA_VALID_COL | SCA_VALID_ROW | SCA_VALID_TAB |
+@@ -701,14 +776,14 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+ }
+
p = tmp2;
- tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
+- tmp1 = lcl_a1_get_col( p+1, &r.aEnd, &nFlags2 );
++ p = lcl_eatWhiteSpace( p+1 );
++ tmp1 = lcl_a1_get_col( p, &r.aEnd, &nFlags2 );
if( !tmp1 ) // strange, but valid singleton
- return lcl_XL_LinkSheetRef( r, pDoc,
- aExternDocName, aStartTabName, aEndTabName, nFlags );
@@ -1593,7 +1937,7 @@
if ( *tmp2 != 0 )
{
-@@ -708,45 +757,31 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
+@@ -719,45 +794,31 @@ lcl_ScRange_Parse_XL_A1( ScRange& r,
}
nFlags |= (nFlags2 << 4);
@@ -1652,7 +1996,7 @@
}
SCCOL nCol = 0;
-@@ -762,25 +797,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -773,25 +834,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
if (*p == '$')
nRes |= SCA_TAB_ABSOLUTE, p++;
@@ -1683,7 +2027,7 @@
while (*p)
{
-@@ -795,35 +816,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -806,35 +853,11 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
}
if( *p++ != '.' )
nBits = 0;
@@ -1723,7 +2067,7 @@
}
else
nBits = 0;
-@@ -884,16 +881,31 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -895,16 +918,31 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
if( !nBits )
p = q;
}
@@ -1761,7 +2105,7 @@
if ( !(nRes & SCA_VALID_ROW) && (nRes & SCA_VALID_COL)
&& !( (nRes & SCA_TAB_3D) && (nRes & SCA_VALID_TAB)) )
{ // keine Row, keine Tab, aber Col => DM (...), B (...) o.ae.
-@@ -912,9 +924,10 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
+@@ -923,9 +961,10 @@ lcl_ScAddress_Parse_OOo( BOOL& bExternal, const sal_Unicode* p,
}
static USHORT
@@ -1775,7 +2119,7 @@
{
if( !*p )
return 0;
-@@ -924,20 +937,22 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
+@@ -935,20 +974,22 @@ lcl_ScAddress_Parse ( BOOL& bExternal, const sal_Unicode* p,
default :
case ScAddress::CONV_OOO:
{
@@ -1801,7 +2145,7 @@
rAddr = r.aStart;
return nFlags;
}
-@@ -949,9 +964,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
+@@ -960,9 +1001,8 @@ bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString,
SCTAB nDefTab, ScRefAddress& rRefAddress,
const ScAddress::Details& rDetails )
{
@@ -1812,7 +2156,7 @@
if( nRes & SCA_VALID )
{
rRefAddress.Set( aAddr,
-@@ -988,10 +1002,11 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
+@@ -999,10 +1039,11 @@ bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab
USHORT ScAddress::Parse( const String& r, ScDocument* pDoc,
@@ -1827,7 +2171,7 @@
}
-@@ -1060,7 +1075,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
+@@ -1071,7 +1112,7 @@ void ScRange::ExtendTo( const ScRange& rRange )
}
static USHORT
@@ -1836,7 +2180,7 @@
{
USHORT nRes1 = 0, nRes2 = 0;
xub_StrLen nTmp = 0;
-@@ -1073,13 +1088,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1084,13 +1125,12 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
String aTmp( r );
sal_Unicode* p = aTmp.GetBufferAccess();
p[ nPos ] = 0;
@@ -1853,7 +2197,7 @@
nRes2 &= ~SCA_VALID_TAB; // #REF!
else
{
-@@ -1132,7 +1146,9 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
+@@ -1143,7 +1183,9 @@ lcl_ScRange_Parse_OOo( ScRange &aRange, const String& r, ScDocument* pDoc )
}
USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
@@ -1864,7 +2208,7 @@
{
if ( r.Len() <= 0 )
return 0;
-@@ -1141,13 +1157,15 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
+@@ -1152,13 +1194,15 @@ USHORT ScRange::Parse( const String& r, ScDocument* pDoc,
{
default :
case ScAddress::CONV_OOO:
@@ -1883,7 +2227,7 @@
}
}
-@@ -1187,6 +1205,7 @@ USHORT ScRange::ParseCols( const String& rStr, ScDocument* pDoc,
+@@ -1198,6 +1242,7 @@ USHORT ScRange::ParseCols( const String& rStr, ScDocument* pDoc,
default :
case ScAddress::CONV_OOO: // No full col refs in OOO yet, assume XL notation
case ScAddress::CONV_XL_A1:
@@ -1891,7 +2235,7 @@
if (NULL != (p = lcl_a1_get_col( p, &aStart, &ignored ) ) )
{
if( p[0] == ':')
-@@ -1245,6 +1264,7 @@ USHORT ScRange::ParseRows( const String& rStr, ScDocument* pDoc,
+@@ -1256,6 +1301,7 @@ USHORT ScRange::ParseRows( const String& rStr, ScDocument* pDoc,
default :
case ScAddress::CONV_OOO: // No full row refs in OOO yet, assume XL notation
case ScAddress::CONV_XL_A1:
@@ -1899,7 +2243,7 @@
if (NULL != (p = lcl_a1_get_row( p, &aStart, &ignored ) ) )
{
if( p[0] == ':')
-@@ -1429,6 +1449,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1440,6 +1486,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
case CONV_XL_A1:
case CONV_XL_R1C1:
@@ -1907,7 +2251,7 @@
if (aDocName.Len() > 0)
{
r += '[';
-@@ -1446,6 +1467,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1457,6 +1504,7 @@ void ScAddress::Format( String& r, USHORT nFlags, ScDocument* pDoc,
default :
case CONV_OOO:
case CONV_XL_A1:
@@ -1915,7 +2259,7 @@
if( nFlags & SCA_VALID_COL )
lcl_a1_append_c ( r, nCol, nFlags & SCA_COL_ABSOLUTE );
if( nFlags & SCA_VALID_ROW )
-@@ -1565,6 +1587,7 @@ void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc,
+@@ -1576,6 +1624,7 @@ void ScRange::Format( String& r, USHORT nFlags, ScDocument* pDoc,
break;
case ScAddress::CONV_XL_A1:
@@ -1923,7 +2267,7 @@
lcl_ScRange_Format_XL_Header( r, *this, nFlags, pDoc, rDetails );
if( aStart.Col() == 0 && aEnd.Col() >= MAXCOL )
{
-@@ -1688,6 +1711,7 @@ String ScAddress::GetColRowString( bool bAbsolute,
+@@ -1699,6 +1748,7 @@ String ScAddress::GetColRowString( bool bAbsolute,
default :
case ScAddress::CONV_OOO:
case ScAddress::CONV_XL_A1:
@@ -1932,7 +2276,7 @@
aString.Append( '$' );
diff --git sc/source/core/tool/compiler.cxx sc/source/core/tool/compiler.cxx
-index 918332d..0910e72 100644
+index ae6adef..f815af9 100644
--- sc/source/core/tool/compiler.cxx
+++ sc/source/core/tool/compiler.cxx
@@ -74,9 +74,11 @@
@@ -1984,15 +2328,15 @@
}
// static
-@@ -737,10 +734,28 @@ void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
+@@ -737,7 +734,25 @@ void ScCompiler::SetFormulaLanguage( const ScCompiler::OpCodeMapPtr & xMap )
}
else
pCharClass = ScGlobal::pCharClass;
+ SetGrammarAndRefConvention( mxSymbols->getGrammar(), GetGrammar());
- }
- }
-
-
++ }
++}
++
++
+void ScCompiler::SetGrammarAndRefConvention(
+ const ScGrammar::Grammar eNewGrammar, const ScGrammar::Grammar eOldGrammar )
+{
@@ -2004,16 +2348,13 @@
+ SetRefConvention( pDoc->GetAddressConvention());
+ else
+ SetRefConvention( pConvOOO_A1);
-+ }
+ }
+ else
+ SetRefConvention( eConv );
-+}
-+
-+
- //-----------------------------------------------------------------------------
+ }
- void ScCompiler::OpCodeMap::putOpCode( const String & rStr, const OpCode eOp )
-@@ -866,20 +881,21 @@ ScCompiler::OpCodeMap::createSequenceOfAvailableMappings( const sal_Int32 nGroup
+
+@@ -866,20 +881,19 @@ ScCompiler::OpCodeMap::createSequenceOfAvailableMappings( const sal_Int32 nGroup
sal_Int32 nOff;
OpCode eOp;
} aMap[] = {
@@ -2031,25 +2372,23 @@
- { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
- { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName } ,
- { FormulaMapGroupSpecialOffset::COL_ROW_NAME_AUTO , ocColRowNameAuto }
-+ { FormulaMapGroupSpecialOffset::PUSH , ocPush } ,
-+ { FormulaMapGroupSpecialOffset::CALL , ocCall } ,
-+ { FormulaMapGroupSpecialOffset::STOP , ocStop } ,
-+ { FormulaMapGroupSpecialOffset::EXTERNAL , ocExternal } ,
-+ { FormulaMapGroupSpecialOffset::NAME , ocName } ,
-+ { FormulaMapGroupSpecialOffset::NO_NAME , ocNoName } ,
-+ { FormulaMapGroupSpecialOffset::MISSING , ocMissing } ,
-+ { FormulaMapGroupSpecialOffset::BAD , ocBad } ,
-+ { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } ,
-+ { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } ,
-+ { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } ,
-+ { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
-+ { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName } ,
-+ { FormulaMapGroupSpecialOffset::COL_ROW_NAME_AUTO , ocColRowNameAuto } ,
-+ { FormulaMapGroupSpecialOffset::EXTERNAL_REFERENCE , ocExternalRef }
++ { FormulaMapGroupSpecialOffset::PUSH , ocPush } ,
++ { FormulaMapGroupSpecialOffset::CALL , ocCall } ,
++ { FormulaMapGroupSpecialOffset::STOP , ocStop } ,
++ { FormulaMapGroupSpecialOffset::EXTERNAL , ocExternal } ,
++ { FormulaMapGroupSpecialOffset::NAME , ocName } ,
++ { FormulaMapGroupSpecialOffset::NO_NAME , ocNoName } ,
++ { FormulaMapGroupSpecialOffset::MISSING , ocMissing } ,
++ { FormulaMapGroupSpecialOffset::BAD , ocBad } ,
++ { FormulaMapGroupSpecialOffset::SPACES , ocSpaces } ,
++ { FormulaMapGroupSpecialOffset::MAT_REF , ocMatRef } ,
++ { FormulaMapGroupSpecialOffset::DB_AREA , ocDBArea } ,
++ { FormulaMapGroupSpecialOffset::MACRO , ocMacro } ,
++ { FormulaMapGroupSpecialOffset::COL_ROW_NAME , ocColRowName }
};
const size_t nCount = sizeof(aMap)/sizeof(aMap[0]);
// Preallocate vector elements.
-@@ -1078,7 +1094,7 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
+@@ -1078,7 +1092,7 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
/* */ t[32] = SC_COMPILER_C_CHAR_DONTCARE | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
/* ! */ t[33] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
if (ScAddress::CONV_ODF == meConv)
@@ -2058,7 +2397,7 @@
/* " */ t[34] = SC_COMPILER_C_CHAR_STRING | SC_COMPILER_C_STRING_SEP;
/* # */ t[35] = SC_COMPILER_C_WORD_SEP;
/* $ */ t[36] = SC_COMPILER_C_CHAR_WORD | SC_COMPILER_C_WORD | SC_COMPILER_C_CHAR_IDENT | SC_COMPILER_C_IDENT;
-@@ -1093,8 +1109,10 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
+@@ -1093,8 +1107,10 @@ ScCompiler::Convention::Convention( ScAddress::Convention eConv )
/* - */ 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[47] = SC_COMPILER_C_CHAR | SC_COMPILER_C_WORD_SEP | SC_COMPILER_C_VALUE_SEP;
@@ -2070,7 +2409,7 @@
/* : */ 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;
-@@ -1102,8 +1120,10 @@ for (i = 48; i < 58; i++)
+@@ -1102,8 +1118,10 @@ for (i = 48; i < 58; i++)
/* > */ 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;
/* @ */ // FREE
@@ -2082,7 +2421,7 @@
if (ScAddress::CONV_ODF == meConv)
{
/* [ */ t[91] = SC_COMPILER_C_ODF_LBRACKET;
-@@ -1119,14 +1139,17 @@ for (i = 65; i < 91; i++)
+@@ -1119,14 +1137,17 @@ for (i = 65; i < 91; i++)
/* ^ */ 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;
/* ` */ // FREE
@@ -2102,7 +2441,7 @@
{
/* */ t[32] |= SC_COMPILER_C_WORD;
/* ! */ t[33] |= SC_COMPILER_C_IDENT | SC_COMPILER_C_WORD;
-@@ -1165,9 +1188,14 @@ for (i = 97; i < 123; i++)
+@@ -1165,9 +1186,14 @@ for (i = 97; i < 123; i++)
if( ScAddress::CONV_XL_R1C1 == meConv )
{
@@ -2120,7 +2459,7 @@
}
}
}
-@@ -1191,7 +1219,7 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
+@@ -1191,7 +1217,7 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
{
rRes.TokenType = KParseType::SINGLE_QUOTE_NAME;
rRes.EndPos = nPos+1;
@@ -2129,7 +2468,7 @@
}
++nPos;
}
-@@ -1199,9 +1227,203 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
+@@ -1199,9 +1225,203 @@ static bool lcl_isValidQuotedText( const String& rFormula, xub_StrLen nSrcPos, P
}
}
@@ -2163,7 +2502,7 @@
+ if (c == '\'')
+ {
+ if (j == i)
-+ {
++ {
+ // empty quote e.g. (=''!Name)
+ return false;
+ }
@@ -2196,13 +2535,13 @@
+ }
+
+ if (!bInName)
-+ {
++ {
+ // premature ending of the quoted segment.
+ return false;
+ }
+
+ if (c != cSep)
-+ {
++ {
+ // only the separator is allowed after the closing quote.
+ return false;
+ }
@@ -2269,9 +2608,9 @@
+
+ rFile = aTmpFile;
+ rName = aTmpName;
-+ return true;
-+}
-+
+ return true;
+ }
+
+static String lcl_makeExternalNameStr( const String& rFile, const String& rName,
+ const sal_Unicode cSep, bool bODF )
+{
@@ -2290,7 +2629,7 @@
+ return String( aBuf.makeStringAndClear());
+}
+
-+static bool lcl_getLastTabName( String& rTabName2, const String& rTabName1,
++static bool lcl_getLastTabName( String& rTabName2, const String& rTabName1,
+ const vector<String>& rTabNames, const ComplRefData& rRef )
+{
+ SCsTAB nTabSpan = rRef.Ref2.nTab - rRef.Ref1.nTab;
@@ -2302,7 +2641,7 @@
+ if (itr == rTabNames.end())
+ {
+ rTabName2 = ScGlobal::GetRscString(STR_NO_REF_TABLE);
-+ return false;
++ return false;
+ }
+
+ size_t nDist = ::std::distance(itrBeg, itr);
@@ -2317,9 +2656,9 @@
+ else
+ rTabName2 = rTabName1;
+
- return true;
- }
-
++ return true;
++}
++
+static void lcl_appendTabName(::rtl::OUStringBuffer& rBuffer, const String& rTabName)
+{
+ bool bQuote = (rTabName.Search(sal_Unicode(' '), 0) != STRING_NOTFOUND);
@@ -2333,7 +2672,7 @@
struct Convention_A1 : public ScCompiler::Convention
{
Convention_A1( ScAddress::Convention eConv ) : ScCompiler::Convention( eConv ) { }
-@@ -1215,14 +1437,14 @@ struct Convention_A1 : public ScCompiler::Convention
+@@ -1215,14 +1435,14 @@ struct Convention_A1 : public ScCompiler::Convention
const CharClass* pCharClass) const
{
ParseResult aRet;
@@ -2350,7 +2689,7 @@
return pCharClass->parseAnyToken( rFormula,
nSrcPos, nStartFlags, aAddAllowed, nContFlags, aAddAllowed );
}
-@@ -1405,6 +1627,114 @@ struct ConventionOOO_A1 : public Convention_A1
+@@ -1405,6 +1625,121 @@ struct ConventionOOO_A1 : public Convention_A1
return sal_Unicode(0);
}
@@ -2365,8 +2704,8 @@
+ return lcl_makeExternalNameStr( rFile, rName, sal_Unicode('#'), false);
+ }
+
-+ bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
-+ const String& rTabName, const SingleRefData& rRef,
++ bool makeExternalSingleRefStr( ::rtl::OUStringBuffer& rBuffer, sal_uInt16 nFileId,
++ const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bDisplayTabName ) const
+ {
+ if (bDisplayTabName)
@@ -2376,12 +2715,12 @@
+ if (p)
+ aFile = *p;
+ aFile.SearchAndReplaceAllAscii("'", String::CreateFromAscii("''"));
-+
++
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(aFile);
+ rBuffer.append(sal_Unicode('\''));
+ rBuffer.append(sal_Unicode('#'));
-+
++
+ // external reference is always 3D and the sheet is absolute.
+ rBuffer.append(sal_Unicode('$'));
+ lcl_appendTabName(rBuffer, rTabName);
@@ -2400,7 +2739,7 @@
+ }
+
+ void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bODF ) const
+ {
+ SingleRefData aRef(rRef);
@@ -2414,14 +2753,14 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
+ }
+
+ void makeExternalRefStrImpl( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr, bool bODF ) const
+ {
+ ComplRefData aRef(rRef);
@@ -2441,23 +2780,30 @@
+ vector<String> aTabNames;
+ pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
+ if (aTabNames.empty())
++ {
++ DBG_ERROR1( "ConventionOOO_A1::makeExternalRefStrImpl: no sheet names for document ID %s", nFileId);
+ break;
++ }
+
+ String aLastTabName;
+ if (!lcl_getLastTabName(aLastTabName, rTabName, aTabNames, aRef))
+ {
+ rBuffer.append(aLastTabName);
++ DBG_ERROR( "ConventionOOO_A1::makeExternalRefStrImpl: sheet name not found");
+ break;
+ }
++ bool bDisplayTabName = (aRef.Ref1.nTab != aRef.Ref2.nTab);
++ if (bODF && !bDisplayTabName)
++ rBuffer.append( sal_Unicode('.')); // need at least the sheet separator in ODF
+ makeExternalSingleRefStr( rBuffer, nFileId, aLastTabName,
-+ aRef.Ref2, pRefMgr, (aRef.Ref1.nTab != aRef.Ref2.nTab));
++ aRef.Ref2, pRefMgr, bDisplayTabName);
+ } while (0);
+ if (bODF)
+ rBuffer.append( sal_Unicode(']'));
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, false);
@@ -2465,7 +2811,7 @@
};
-@@ -1423,6 +1753,25 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
+@@ -1423,6 +1758,25 @@ struct ConventionOOO_A1_ODF : public ConventionOOO_A1
{
MakeRefStrImpl( rBuffer, rComp, rRef, bSingleRef, true);
}
@@ -2476,14 +2822,14 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ makeExternalRefStrImpl( rBuffer, rCompiler, nFileId, rTabName, rRef, pRefMgr, true);
@@ -2491,7 +2837,7 @@
};
static const ConventionOOO_A1_ODF ConvOOO_A1_ODF;
-@@ -1526,11 +1875,129 @@ struct ConventionXL
+@@ -1526,11 +1880,129 @@ struct ConventionXL
}
return sal_Unicode(0);
}
@@ -2508,11 +2854,11 @@
+
+ static void makeExternalDocStr( ::rtl::OUStringBuffer& rBuffer, const String& rFullName )
+ {
-+ // Format that is easier to deal with inside OOo, because we use file
++ // 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
+ // it the way Gnumeric does it. Gnumeric doesn't use the URL form
+ // and allows relative file path.
-+ //
++ //
+ // ['file:///path/to/source/filename.xls']
+
+ rBuffer.append(sal_Unicode('['));
@@ -2530,14 +2876,14 @@
+ rBuffer.append(sal_Unicode(']'));
+ }
+
-+ static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const String& rTabName,
++ static void makeExternalTabNameRange( ::rtl::OUStringBuffer& rBuf, const String& rTabName,
+ const vector<String>& rTabNames,
+ const ComplRefData& rRef )
+ {
+ String aLastTabName;
+ if (!lcl_getLastTabName(aLastTabName, rTabName, rTabNames, rRef))
+ {
-+ rBuf.append(aLastTabName);
++ rBuf.append(aLastTabName);
+ return;
+ }
+
@@ -2572,7 +2918,7 @@
+ else if (c == '\'')
+ {
+ if (cPrev == '\'')
-+ // two successive single quote is treated as a single
++ // two successive single quote is treated as a single
+ // valid character.
+ c = 'a';
+ }
@@ -2594,7 +2940,7 @@
+ {
+ // any other character
+ if (i > rSrcPos + 2 && cPrev == '\'')
-+ // unless it's the 3rd character, a normal character
++ // unless it's the 3rd character, a normal character
+ // following immediately a single quote is invalid.
+ return;
+ }
@@ -2621,7 +2967,7 @@
void MakeRefStr( rtl::OUStringBuffer& rBuf,
const ScCompiler& rComp,
const ComplRefData& rRef,
-@@ -1584,22 +2051,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1584,22 +2056,11 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
}
}
@@ -2646,7 +2992,7 @@
}
}
-@@ -1607,8 +2063,10 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1607,8 +2068,10 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
xub_StrLen nSrcPos,
const CharClass* pCharClass) const
{
@@ -2658,7 +3004,7 @@
return aRet;
static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
-@@ -1624,11 +2082,83 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
+@@ -1624,11 +2087,83 @@ struct ConventionXL_A1 : public Convention_A1, public ConventionXL
{
return ConventionXL::getSpecialSymbol(eSymType);
}
@@ -2674,13 +3020,13 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
+ // This is a little different from the format Excel uses, as Excel
+ // puts [] only around the file name. But we need to enclose the
-+ // whole file path with [] because the file name can contain any
++ // whole file path with [] because the file name can contain any
+ // characters.
+
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2698,7 +3044,7 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2742,7 +3088,7 @@
//-----------------------------------------------------------------------------
static void
-@@ -1733,8 +2263,10 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
+@@ -1733,8 +2268,10 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
xub_StrLen nSrcPos,
const CharClass* pCharClass) const
{
@@ -2754,7 +3100,7 @@
return aRet;
static const sal_Int32 nStartFlags = KParseTokens::ANY_LETTER_OR_NUMBER |
-@@ -1751,6 +2283,96 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
+@@ -1751,6 +2288,96 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL
{
return ConventionXL::getSpecialSymbol(eSymType);
}
@@ -2770,13 +3116,13 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const SingleRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ // ['file:///path/to/file/filename.xls']'Sheet Name'!$A$1
+ // This is a little different from the format Excel uses, as Excel
+ // puts [] only around the file name. But we need to enclose the
-+ // whole file path with [] because the file name can contain any
++ // whole file path with [] because the file name can contain any
+ // characters.
+
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2795,7 +3141,7 @@
+ }
+
+ virtual void makeExternalRefStr( ::rtl::OUStringBuffer& rBuffer, const ScCompiler& rCompiler,
-+ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
++ sal_uInt16 nFileId, const String& rTabName, const ComplRefData& rRef,
+ ScExternalRefManager* pRefMgr ) const
+ {
+ const String* pFullName = pRefMgr->getExternalFileName(nFileId);
@@ -2851,7 +3197,7 @@
};
static const ConventionXL_R1C1 ConvXL_R1C1;
-@@ -1817,13 +2439,15 @@ void ScCompiler::CheckTabQuotes( String& rString,
+@@ -1817,13 +2444,15 @@ void ScCompiler::CheckTabQuotes( String& rString,
KParseType::IDENTNAME, rString, 0, nStartFlags, EMPTY_STRING, nContFlags, EMPTY_STRING);
bool bNeedsQuote = !((aRes.TokenType & KParseType::IDENTNAME) && aRes.EndPos == rString.Len());
@@ -2868,7 +3214,7 @@
if( bNeedsQuote )
{
static const String one_quote = static_cast<sal_Unicode>( '\'' );
-@@ -1859,6 +2483,7 @@ void ScCompiler::SetRefConvention( ScAddress::Convention eConv )
+@@ -1859,6 +2488,7 @@ void ScCompiler::SetRefConvention( ScAddress::Convention eConv )
case ScAddress::CONV_ODF : SetRefConvention( pConvOOO_A1_ODF ); break;
case ScAddress::CONV_XL_A1 : SetRefConvention( pConvXL_A1 ); break;
case ScAddress::CONV_XL_R1C1 : SetRefConvention( pConvXL_R1C1 ); break;
@@ -2876,35 +3222,162 @@
}
}
-@@ -2208,7 +2833,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
- static const int kQuote = kInc * 2;
- static const int kPast = kInc * 3;
+@@ -2191,71 +2821,88 @@ Label_MaskStateMachine:
+ }
+ // fall through and follow logic
+ case ssSkipReference:
+- // ODF reference: [$'Sheet'.A1:.B2] with dots being mandatory
+- // also if no sheet name.
+- //
+- // nRefInSheetName: 0 := not in sheet name yet.
+- // +1 := encountered leading '$'
+- // +2 := encountered opening ''', which
+- // may be after $ or not.
+- // 4(+ ) := somewhere in sheet name.
+- // 8(+ ) := encountered ''' in sheet name,
+- // will be decremented (-4) again if
+- // double or incremented (+4) again
+- // if not.
+- // 12(+ ) := past closing ''' or no sheet name
+- // and past leading '.'
++ // ODF reference: ['External'#$'Sheet'.A1:.B2] with dots being
++ // mandatory also if no sheet name. 'External'# is optional,
++ // sheet name is optional, quotes around sheet name are
++ // optional if no quote contained.
+ {
+- // kOpen can be used in bit tests in this arrangement
+- static const int kDollar = 1;
+- static const int kOpen = 2;
+- static const int kInc = 4;
+- static const int kSheet = kInc * 1;
+- static const int kQuote = kInc * 2;
+- static const int kPast = kInc * 3;
++
++ // nRefInSheetName: 0 := not in sheet name yet. 'External'
++ // is parsed as if it was a sheet name and nRefInSheetName
++ // is reset when # is encountered immediately after closing
++ // quote.
++
++ // Encountered leading $.
++ static const int kDollar = (1 << 1);
++ // Encountered ' opening quote, which may be after $ or
++ // not.
++ static const int kOpen = (1 << 2);
++ // Somewhere in sheet name.
++ static const int kSheet = (1 << 3);
++ // Encountered ' in sheet name, will be cleared if double
++ // or transformed to kClose if not, in which case kOpen is
++ // cleared.
++ static const int kQuote = (1 << 4);
++ // Past ' closing quote.
++ static const int kClose = (1 << 5);
++ // Past . sheet name separator.
++ static const int kPast = (1 << 6);
++
bool bAddToSymbol = true;
- if ('.' == c && nRefInSheetName == 0)
+ if (cSheetSep == c && nRefInSheetName == 0)
{
- // eat it, no sheet name
+- // eat it, no sheet name
++ // eat it, no sheet name [.A1]
bAddToSymbol = false;
-@@ -2223,7 +2848,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray)
+- nRefInSheetName = kPast;
++ nRefInSheetName |= kPast;
}
- else if (nRefInSheetName < kPast)
+- else if (':' == c && nRefInSheetName < kSheet)
++ else if (!(nRefInSheetName & kPast))
{
+- DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
+- "range operator ':' without prior sheet name separator '.' violates ODF spec");
+- nRefInSheetName = 0;
+- ++mnPredetectedReference;
+- }
+- else if (nRefInSheetName < kPast)
+- {
- if ('$' == c && nRefInSheetName < kDollar)
-+ if (cSheetPrefix == c && nRefInSheetName < kDollar)
- nRefInSheetName += kDollar;
+- nRefInSheetName += kDollar;
++ if (nMask & SC_COMPILER_C_ODF_RBRACKET &&
++ !(nRefInSheetName & kOpen))
++ {
++ DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
++ "closing bracket ']' without prior sheet name separator '.' violates ODF spec");
++ // eaten, not added to pSym
++ bAddToSymbol = false;
++ eState = ssStop;
++ }
++ else if (cSheetPrefix == c && nRefInSheetName == 0)
++ nRefInSheetName |= kDollar;
else if ('\'' == c)
{
-@@ -2545,7 +3170,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
- {
- ScRange aRange( aPos, aPos );
- const ScAddress::Details aDetails( pConv->meConv, aPos );
-- USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
-+ ScAddress::ExternalInfo aExtInfo;
-+ USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
+- if (nRefInSheetName < kSheet)
+- nRefInSheetName += kOpen + kSheet;
++ if (!(nRefInSheetName & kSheet))
++ nRefInSheetName |= (kOpen | kSheet);
+ else if (!(nRefInSheetName & kOpen))
+ {
+- DBG_ERRORFILE("ScCompiler::NextSymbol: reference:"
++ DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
+ "a ''' without the sheet name being enclosed in '...' violates ODF spec");
+ }
+- else if (nRefInSheetName >= kQuote)
++ else if (nRefInSheetName & kQuote)
+ // escaped embedded quote
+- nRefInSheetName -= kInc;
++ nRefInSheetName &= ~kQuote;
+ else
+ // a quote in (or after) sheet name
+- nRefInSheetName += kInc;
++ nRefInSheetName |= kQuote;
+ }
+- else if ('.' == c && !(nRefInSheetName & kOpen))
++ else if (cSheetSep == c && !(nRefInSheetName & kOpen))
+ // unquoted sheet name separator
+- nRefInSheetName += kPast;
+- else if (nRefInSheetName < kSheet)
++ nRefInSheetName |= kPast;
++ else if (':' == c && !(nRefInSheetName & kOpen))
++ {
++ DBG_ERRORFILE("ScCompiler::NextSymbol: reference: "
++ "range operator ':' without prior sheet name separator '.' violates ODF spec");
++ nRefInSheetName = 0;
++ ++mnPredetectedReference;
++ }
++ else if (!(nRefInSheetName & kSheet))
+ // start unquoted sheet name
+- nRefInSheetName += kSheet;
+- else if (nRefInSheetName >= kQuote)
+- // quote not followed by quote => past
+- nRefInSheetName += kInc;
++ nRefInSheetName |= kSheet;
++ else if (nRefInSheetName & kQuote)
++ {
++ // quote not followed by quote => close
++ nRefInSheetName |= kClose;
++ nRefInSheetName &= ~kOpen;
++ }
+ }
+ else if (':' == c)
+ {
+@@ -2270,7 +2917,7 @@ Label_MaskStateMachine:
+ eState = ssStop;
+ }
+ if (bAddToSymbol && eState != ssSkipReference)
+- *pSym++ = c; // everything is part of sheet reference
++ *pSym++ = c; // everything is part of reference
+ }
+ break;
+ case ssStop:
+@@ -2551,7 +3198,8 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+ {
+ ScRange aRange( aPos, aPos );
+ const ScAddress::Details aDetails( pConv->meConv, aPos );
+- USHORT nFlags = aRange.Parse( rName, pDoc, aDetails );
++ ScAddress::ExternalInfo aExtInfo;
++ USHORT nFlags = aRange.Parse( rName, pDoc, aDetails, &aExtInfo, &maExternalLinks );
if( nFlags & SCA_VALID )
{
ScRawToken aToken;
-@@ -2564,7 +3190,17 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
+@@ -2570,7 +3218,17 @@ BOOL ScCompiler::IsDoubleReference( const String& rName )
aRef.Ref2.SetTabDeleted( TRUE ); // #REF!
aRef.Ref2.SetFlag3D( ( nFlags & SCA_TAB2_3D ) != 0 );
aRef.CalcRelFromAbs( aPos );
@@ -2923,7 +3396,7 @@
pRawToken = aToken.Clone();
}
-@@ -2576,7 +3212,8 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
+@@ -2582,7 +3240,8 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
{
ScAddress aAddr( aPos );
const ScAddress::Details aDetails( pConv->meConv, aPos );
@@ -2933,7 +3406,7 @@
// Something must be valid in order to recognize Sheet1.blah or blah.a1
// as a (wrong) reference.
if( nFlags & ( SCA_VALID_COL|SCA_VALID_ROW|SCA_VALID_TAB ) )
-@@ -2600,7 +3237,16 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
+@@ -2606,7 +3265,16 @@ BOOL ScCompiler::IsSingleReference( const String& rName )
nFlags |= SCA_VALID;
}
aRef.CalcRelFromAbs( aPos );
@@ -2951,7 +3424,7 @@
pRawToken = aToken.Clone();
}
-@@ -2708,6 +3354,32 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
+@@ -2714,6 +3382,32 @@ BOOL ScCompiler::IsNamedRange( const String& rUpperName )
return FALSE;
}
@@ -2984,7 +3457,7 @@
BOOL ScCompiler::IsDBRange( const String& rName )
{
USHORT n;
-@@ -3243,7 +3915,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
+@@ -3249,7 +3943,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
if (mnPredetectedReference)
{
String aStr( cSymbol);
@@ -2993,7 +3466,7 @@
{
/* TODO: it would be nice to generate a #REF! error here, which
* would need an ocBad token with additional error value.
-@@ -3306,6 +3978,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
+@@ -3312,6 +4006,7 @@ BOOL ScCompiler::NextNewToken( bool bInArray )
&& !(bAllowBooleans && IsBoolean( aUpper ))
&& !IsValue( aUpper )
&& !IsNamedRange( aUpper )
@@ -3001,7 +3474,7 @@
&& !IsDBRange( aUpper )
&& !IsColRowName( aUpper )
&& !(bMayBeFuncName && IsMacro( aUpper ))
-@@ -3628,9 +4301,9 @@ BOOL ScCompiler::GetToken()
+@@ -3634,9 +4329,9 @@ BOOL ScCompiler::GetToken()
else
{
if ( nWasColRowName >= 2 && pToken->GetOpCode() == ocColRowName )
@@ -3013,86 +3486,58 @@
}
}
}
-@@ -3641,6 +4314,78 @@ BOOL ScCompiler::GetToken()
+@@ -3647,6 +4342,50 @@ BOOL ScCompiler::GetToken()
}
if( pToken->GetOpCode() == ocSubTotal )
glSubTotal = TRUE;
+ else if ( pToken->GetOpCode() == ocExternalRef )
+ {
-+ // Handle external single and double references, or names.
-+
-+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
-+ const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
-+ if (!pFile)
-+ SetError(errNoName);
-+
++ // Handle external range names.
+ switch (pToken->GetType())
+ {
-+ case svExternalName:
-+ {
-+ const String& rName = pToken->GetString();
-+ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(pToken->GetIndex(), rName, &aPos);
-+ if (xNew.get())
-+ {
-+ ScTokenArray* pNew = xNew->Clone();
-+ PushTokenArray(pNew, true);
-+ pNew->Reset();
-+ return GetToken();
-+ }
-+ }
-+ break;
+ case svExternalSingleRef:
++ case svExternalDoubleRef:
++ pArr->nRefs++;
++ break;
++ case svExternalName:
+ {
-+ SingleRefData aData(pToken->GetSingleRef());
-+ if (aData.IsTabRel())
-+ {
-+ DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!")
-+ break;
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ const String* pFile = pRefMgr->getExternalFileName(pToken->GetIndex());
++ if (!pFile)
++ {
++ SetError(errNoName);
++ return true;
+ }
+
-+ aData.CalcAbsIfRel(aPos);
-+ ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
-+ ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(pToken->GetIndex(), pToken->GetString(), aAddr, &aPos, NULL);
-+ if (xNew.get())
-+ {
-+ pToken = xNew->Clone();
++ const String& rName = pToken->GetString();
++ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getRangeNameTokens(
++ pToken->GetIndex(), rName, &aPos);
++
++ if (!xNew)
++ {
++ SetError(errNoName);
+ return true;
+ }
-+ }
-+ break;
-+ case svExternalDoubleRef:
-+ {
-+ ComplRefData aData(pToken->GetDoubleRef());
-+ if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
-+ {
-+ DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!")
-+ break;
-+ }
+
-+ aData.CalcAbsIfRel(aPos);
-+ ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
-+ aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
-+ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(pToken->GetIndex(), pToken->GetString(), aRange, &aPos);
-+ if (xNew.get())
++ ScTokenArray* pNew = xNew->Clone();
++ PushTokenArray( pNew, true);
++ if (pNew->GetNextReference() != NULL)
+ {
-+ ScTokenArray* pNew = xNew->Clone();
-+ PushTokenArray(pNew, true);
-+ pNew->Reset();
-+ return GetToken();
++ SetRelNameReference();
++ MoveRelWrap();
+ }
++ pNew->Reset();
++ return GetToken();
+ }
+ break;
+ default:
-+ {
+ DBG_ERROR1( "ScCompiler::GetToken: unhandled ocExternalRef type %d", pToken->GetType());
-+ }
+ }
-+ SetError(errNoName);
+ }
else if( pToken->GetOpCode() == ocName )
{
ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() );
-@@ -3796,7 +4541,7 @@ BOOL ScCompiler::GetToken()
+@@ -3802,7 +4541,7 @@ BOOL ScCompiler::GetToken()
{ // next defined RowNameRange to the right limits column
const ScRange& rRange = pR->GetRange(1);
if ( rRange.aStart.Row() <= nRow && nRow <= rRange.aEnd.Row() )
@@ -3101,7 +3546,46 @@
SCCOL nTmp = rRange.aStart.Col();
if ( nStartCol < nTmp && nTmp <= nMaxCol )
nMaxCol = nTmp - 1;
-@@ -5638,111 +6383,144 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
+@@ -4426,6 +5165,11 @@ void ScCompiler::Factor()
+ bCorrected = TRUE;
+ }
+ }
++ else if ( eOp == ocExternalRef )
++ {
++ PutCode(pToken);
++ eOp = NextToken();
++ }
+ else
+ {
+ SetError( errUnknownToken );
+@@ -4707,7 +5451,7 @@ void ScCompiler::MoveRelWrap()
+ for( ScToken* t = pArr->GetNextReference(); t;
+ t = pArr->GetNextReference() )
+ {
+- if ( t->GetType() == svSingleRef )
++ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+ else
+ ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() );
+@@ -4724,7 +5468,7 @@ void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc,
+ for( ScToken* t = rArr.GetNextReference(); t;
+ t = rArr.GetNextReference() )
+ {
+- if ( t->GetType() == svSingleRef )
++ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+ ScRefUpdate::MoveRelWrap( pDoc, rPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() );
+ else
+ ScRefUpdate::MoveRelWrap( pDoc, rPos, t->GetDoubleRef() );
+@@ -4836,7 +5580,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode,
+ else if( t->GetType() != svIndex ) // it may be a DB area!!!
+ {
+ t->CalcAbsIfRel( rOldPos );
+- if ( t->GetType() == svSingleRef )
++ if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef )
+ {
+ if ( ScRefUpdate::Update( pDoc, eUpdateRefMode, aPos,
+ r, nDx, nDy, nDz,
+@@ -5641,111 +6385,144 @@ ScToken* ScCompiler::CreateStringFromToken( rtl::OUStringBuffer& rBuffer, ScToke
DBG_ERRORFILE("unknown OpCode");
rBuffer.append(ScGlobal::GetRscString(STR_NO_NAME_REF));
}
@@ -3332,8 +3816,111 @@
if( bSpaces )
rBuffer.append(sal_Unicode(' '));
if ( bAllowArrAdvance )
+diff --git sc/source/core/tool/interpr4.cxx sc/source/core/tool/interpr4.cxx
+index 5f6faa3..b5f9856 100644
+--- sc/source/core/tool/interpr4.cxx
++++ sc/source/core/tool/interpr4.cxx
+@@ -74,6 +74,7 @@
+ #include "addinlis.hxx"
+ #include "jumpmatrix.hxx"
+ #include "parclass.hxx"
++#include "externalrefmgr.hxx"
+
+ using namespace com::sun::star;
+
+@@ -2980,6 +2981,82 @@ void ScInterpreter::ScColRowNameAuto()
+ PushError( errNoRef );
+ }
+
++void ScInterpreter::ScExternalRef()
++{
++ ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager();
++ const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex());
++ if (!pFile)
++ PushError(errNoName);
++
++ switch (pCur->GetType())
++ {
++ case svExternalSingleRef:
++ {
++ SingleRefData aData(pCur->GetSingleRef());
++ if (aData.IsTabRel())
++ {
++ DBG_ERROR("ScCompiler::GetToken: external single reference must have an absolute table reference!");
++ break;
++ }
++
++ aData.CalcAbsIfRel(aPos);
++ ScAddress aAddr(aData.nCol, aData.nRow, aData.nTab);
++ ScExternalRefCache::CellFormat aFmt;
++ ScExternalRefCache::TokenRef xNew = pRefMgr->getSingleRefToken(
++ pCur->GetIndex(), pCur->GetString(), aAddr, &aPos, NULL, &aFmt);
++
++ if (!xNew)
++ break;
++
++ PushTempToken( *xNew); // push a clone
++
++ if (aFmt.mbIsSet)
++ {
++ nFuncFmtType = aFmt.mnType;
++ nFuncFmtIndex = aFmt.mnIndex;
++ }
++ return;
++ }
++ break;
++ case svExternalDoubleRef:
++ {
++ ComplRefData aData(pCur->GetDoubleRef());
++ if (aData.Ref1.IsTabRel() || aData.Ref2.IsTabRel())
++ {
++ DBG_ERROR("ScCompiler::GetToken: external double reference must have an absolute table reference!");
++ break;
++ }
++
++ aData.CalcAbsIfRel(aPos);
++ ScRange aRange(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab,
++ aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
++ ScExternalRefCache::TokenArrayRef xNew = pRefMgr->getDoubleRefTokens(
++ pCur->GetIndex(), pCur->GetString(), aRange, &aPos);
++
++ if (!xNew)
++ break;
++
++ ScToken* p = xNew->First();
++ if (p->GetType() != svMatrix)
++ break;
++
++ if (xNew->Next())
++ {
++ // Can't handle more than one matrix per parameter.
++ SetError( errIllegalArgument);
++ break;
++ }
++
++ PushMatrix(p->GetMatrix());
++ return;
++ }
++ break;
++ default:
++ ;
++ }
++ PushError(errNoRef);
++}
++
+ // --- internals ------------------------------------------------------------
+
+
+@@ -3412,6 +3489,7 @@ StackVar ScInterpreter::Interpret()
+ case ocDBArea : ScDBArea(); break;
+ case ocColRowNameAuto : ScColRowNameAuto(); break;
+ // separated case ocPush : Push( (ScToken&) *pCur ); break;
++ case ocExternalRef : ScExternalRef(); break;
+ case ocIf : ScIfJump(); break;
+ case ocChose : ScChoseJump(); break;
+ case ocAdd : ScAdd(); break;
diff --git sc/source/core/tool/refdata.cxx sc/source/core/tool/refdata.cxx
-index 4ac1814..7ec74d8 100644
+index 0d98f15..3a32461 100644
--- sc/source/core/tool/refdata.cxx
+++ sc/source/core/tool/refdata.cxx
@@ -200,6 +200,10 @@ BOOL SingleRefData::operator==( const SingleRefData& r ) const
@@ -3348,7 +3935,7 @@
static void lcl_putInOrder( SingleRefData & rRef1, SingleRefData & rRef2 )
{
diff --git sc/source/core/tool/token.cxx sc/source/core/tool/token.cxx
-index a20cbd5..87f45c3 100644
+index a20cbd5..e7aa461 100644
--- sc/source/core/tool/token.cxx
+++ sc/source/core/tool/token.cxx
@@ -54,6 +54,8 @@
@@ -3360,7 +3947,7 @@
// ImpTokenIterator wird je Interpreter angelegt, mehrfache auch durch
// SubCode via ScTokenIterator Push/Pop moeglich
IMPL_FIXEDMEMPOOL_NEWDEL( ImpTokenIterator, 32, 16 )
-@@ -209,6 +211,48 @@ void ScRawToken::SetName( USHORT n )
+@@ -193,6 +195,48 @@ void ScRawToken::SetDouble(double rVal)
nRefCnt = 0;
}
@@ -3406,9 +3993,9 @@
+ extname.cName[n] = 0;
+}
+
- ComplRefData& ScRawToken::GetReference()
+ void ScRawToken::SetInt(int rVal)
{
- DBG_ASSERT( lcl_IsReference( eOp, GetType() ), "GetReference: no Ref" );
+ eOp = ocPush;
@@ -260,22 +304,34 @@ ScRawToken* ScRawToken::Clone() const
static USHORT nOffset = lcl_ScRawTokenOffset(); // offset of sbyte
USHORT n = nOffset;
@@ -3885,7 +4472,25 @@
short* ScJumpToken::GetJump() const { return pJump; }
BOOL ScJumpToken::operator==( const ScToken& r ) const
-@@ -1242,6 +1514,9 @@ ScToken* ScTokenArray::GetNextReferenceOrName()
+@@ -1193,6 +1465,8 @@ ScToken* ScTokenArray::GetNextReference()
+ {
+ case svSingleRef:
+ case svDoubleRef:
++ case svExternalSingleRef:
++ case svExternalDoubleRef:
+ return t;
+ default:
+ {
+@@ -1223,6 +1497,8 @@ ScToken* ScTokenArray::GetNextReferenceRPN()
+ {
+ case svSingleRef:
+ case svDoubleRef:
++ case svExternalSingleRef:
++ case svExternalDoubleRef:
+ return t;
+ default:
+ {
+@@ -1242,6 +1518,9 @@ ScToken* ScTokenArray::GetNextReferenceOrName()
case svSingleRef:
case svDoubleRef:
case svIndex:
@@ -3895,7 +4500,7 @@
return t;
default:
{
-@@ -1785,10 +2060,11 @@ ScToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
+@@ -1785,10 +2064,11 @@ ScToken* ScTokenArray::MergeRangeReference( const ScAddress & rPos )
if (!pCode || !nLen)
return NULL;
USHORT nIdx = nLen;
@@ -3911,7 +4516,7 @@
{
ScTokenRef p = ScToken::ExtendRangeReference( *p1, *p3, rPos, true);
if (p)
-@@ -1893,6 +2169,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
+@@ -1893,6 +2173,21 @@ ScToken* ScTokenArray::AddMatrix( ScMatrix* p )
return Add( new ScMatrixToken( p ) );
}
@@ -3960,7 +4565,7 @@
{
DBG_ASSERT_BIFF( GetBiff() == EXC_BIFF5 );
diff --git sc/source/filter/excel/excform8.cxx sc/source/filter/excel/excform8.cxx
-index ebf8543..e0467a0 100644
+index ebf8543..0af6d65 100644
--- sc/source/filter/excel/excform8.cxx
+++ sc/source/filter/excel/excform8.cxx
@@ -41,6 +41,18 @@
@@ -4027,7 +4632,7 @@
- aStack << aPool.Store( ocNoName, pExtName->GetName() );
- GetTracer().TraceFormulaExtName();
+ sal_uInt16 nFileId;
-+ if (!GetExternalFileIdFromXti(nXtiIndex, nFileId))
++ if (!GetExternalFileIdFromXti(nXtiIndex, nFileId) || !pExtName->HasFormulaTokens())
+ {
+ aStack << aPool.Store(ocNoName, pExtName->GetName());
+ break;
@@ -4245,7 +4850,7 @@
}
break;
default: bError = TRUE;
-@@ -1143,7 +1206,130 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
+@@ -1143,7 +1206,152 @@ ConvErr ExcelToSc8::Convert( _ScRangeListTabs& rRangeList, XclImpStream& aIn, sa
return eRet;
}
@@ -4287,7 +4892,7 @@
+ // #98524# always reset flags
+ aSRD.InitFlags();
+ aCRD.InitFlags();
-+
+
+ switch( nOp )
+ {
+ case 0x1C: // Error Value
@@ -4328,7 +4933,7 @@
+ ExcRelToScRel8(nRow, nGrbitCol, aSRD, true);
+ aCRD.Ref1 = aCRD.Ref2 = aSRD;
+ String aTabName = rTabNames[nExtTab1];
-
++
+ if (nExtTab1 == nExtTab2)
+ {
+ // single cell reference
@@ -4342,6 +4947,28 @@
+ }
+ }
+ break;
++ case 0x3B:
++ {
++ // area reference
++ sal_uInt16 nExtTab1, nExtTab2, nRow1, nRow2, nGrbitCol1, nGrbitCol2;
++ rStrm >> nExtTab1 >> nExtTab2 >> nRow1 >> nRow2 >> nGrbitCol1 >> nGrbitCol2;
++ SingleRefData& rR1 = aCRD.Ref1;
++ SingleRefData& rR2 = aCRD.Ref2;
++
++ rR1.nTab = nExtTab1;
++ rR1.SetFlag3D(true);
++ rR1.SetTabRel(false);
++ ExcRelToScRel8(nRow1, nGrbitCol1, rR1, true);
++
++ rR2.nTab = nExtTab2;
++ rR2.SetFlag3D(true);
++ rR2.SetTabRel(false);
++ ExcRelToScRel8(nRow2, nGrbitCol2, rR2, true);
++
++ String aTabName = rTabNames[nExtTab1];
++ aStack << aPool.StoreExtRef(nFileId, aTabName, aCRD);
++ }
++ break;
+ default:
+ bError = true;
+ }
@@ -4377,7 +5004,7 @@
void ExcelToSc8::ExcRelToScRel8( UINT16 nRow, UINT16 nC, SingleRefData &rSRD, const BOOL bName )
{
diff --git sc/source/filter/excel/read.cxx sc/source/filter/excel/read.cxx
-index 2cc592c..7f1c44b 100644
+index eea6293..a868e17 100644
--- sc/source/filter/excel/read.cxx
+++ sc/source/filter/excel/read.cxx
@@ -967,7 +967,7 @@ FltError ImportExcel8::Read( void )
@@ -4533,7 +5160,7 @@
diff --git sc/source/filter/excel/xeformula.cxx sc/source/filter/excel/xeformula.cxx
-index 3db8da7..6488f69 100644
+index 3db8da7..dd46fd7 100644
--- sc/source/filter/excel/xeformula.cxx
+++ sc/source/filter/excel/xeformula.cxx
@@ -42,6 +42,11 @@
@@ -4614,7 +5241,7 @@
+ USHORT nFileId = rTokData.mpScToken->GetIndex();
+ switch (eType)
+ {
-+ case svSingleRef:
++ case svExternalSingleRef:
+ {
+ if (!mpScBasePos)
+ {
@@ -4650,7 +5277,7 @@
+ AppendAddress(aXclPos);
+ }
+ break;
-+ case svDoubleRef:
++ case svExternalDoubleRef:
+ {
+ if (!mpScBasePos)
+ {
@@ -4768,7 +5395,7 @@
SCTAB XclExpFmlaCompImpl::GetScTab( const SingleRefData& rRefData ) const
diff --git sc/source/filter/excel/xelink.cxx sc/source/filter/excel/xelink.cxx
-index b1bacad..d929e21 100644
+index b1bacad..b46e813 100644
--- sc/source/filter/excel/xelink.cxx
+++ sc/source/filter/excel/xelink.cxx
@@ -38,6 +38,14 @@
@@ -4914,7 +5541,7 @@
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry ) = 0;
+
/** Derived classes store all cells in the given range in a CRN record list. */
@@ -4942,7 +5569,7 @@
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry );
+
virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
@@ -4970,7 +5597,7 @@
virtual sal_uInt16 FindExtSheet( sal_Unicode cCode );
+ virtual void FindExtSheet( sal_uInt16 nFileId, const String& rTabName, sal_uInt16 nXclTabSpan,
-+ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
++ sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
+ XclExpRefLogEntry* pRefLogEntry );
+
virtual void StoreCellRange( const SingleRefData& rRef1, const SingleRefData& rRef2 );
@@ -5009,7 +5636,7 @@
+
+void XclExpExtName::WriteAddData( XclExpStream& rStrm )
+{
-+ // Write only if it only has a single token that is either a cell or cell
++ // Write only if it only has a single token that is either a cell or cell
+ // range address. Excel just writes '02 00 1C 17' for all the other types
+ // of external names.
+
@@ -5032,8 +5659,8 @@
+
+ bool bColRel = rRef.IsColRel();
+ bool bRowRel = rRef.IsRowRel();
-+ sal_uInt16 nCol = bColRel ? rRef.nRelCol : rRef.nCol;
-+ sal_uInt16 nRow = bRowRel ? rRef.nRelRow : rRef.nRow;
++ sal_uInt16 nCol = static_cast< sal_uInt16 >( bColRel ? rRef.nRelCol : rRef.nCol );
++ sal_uInt16 nRow = static_cast< sal_uInt16 >( bRowRel ? rRef.nRelRow : rRef.nRow );
+ if (bColRel) nCol |= 0x4000;
+ if (bRowRel) nCol |= 0x8000;
+
@@ -5063,10 +5690,10 @@
+ bool bCol2Rel = r2.IsColRel();
+ bool bRow2Rel = r2.IsRowRel();
+
-+ sal_uInt16 nCol1 = bCol1Rel ? r1.nRelCol : r1.nCol;
-+ sal_uInt16 nCol2 = bCol2Rel ? r2.nRelCol : r2.nCol;
-+ sal_uInt16 nRow1 = bRow1Rel ? r1.nRelRow : r1.nRow;
-+ sal_uInt16 nRow2 = bRow2Rel ? r2.nRelRow : r2.nRow;
++ sal_uInt16 nCol1 = static_cast< sal_uInt16 >( bCol1Rel ? r1.nRelCol : r1.nCol );
++ sal_uInt16 nCol2 = static_cast< sal_uInt16 >( bCol2Rel ? r2.nRelCol : r2.nCol );
++ sal_uInt16 nRow1 = static_cast< sal_uInt16 >( bRow1Rel ? r1.nRelRow : r1.nRow );
++ sal_uInt16 nRow2 = static_cast< sal_uInt16 >( bRow2Rel ? r2.nRelRow : r2.nRow );
+ if (bCol1Rel) nCol1 |= 0x4000;
+ if (bRow1Rel) nCol1 |= 0x8000;
+ if (bCol2Rel) nCol2 |= 0x4000;
@@ -5080,7 +5707,7 @@
+ // operator token (3B for area reference)
+ rStrm << static_cast<sal_uInt8>(0x3B);
+ // range (area) address
-+ sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
++ sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
+ rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
+ return;
+ }
@@ -5158,16 +5785,16 @@
+ pMtx->GetDimensions(nCols, nRows);
+ const ScAddress& s = rRange.aStart;
+ const ScAddress& e = rRange.aEnd;
-+ if (static_cast<SCCOL>(nCols) != e.Col() - s.Col() + 1 ||
++ if (static_cast<SCCOL>(nCols) != e.Col() - s.Col() + 1 ||
+ static_cast<SCROW>(nRows) != e.Row() - s.Row() + 1)
+ {
+ // size mis-match!
+ return;
+ }
+
-+ for (SCSIZE nCol = 0; nCol < nCols; ++nCol)
++ for (SCCOL nCol = 0; nCol < static_cast< SCCOL >( nCols ); ++nCol)
+ {
-+ for (SCSIZE nRow = 0; nRow < nRows; ++nRow)
++ for (SCROW nRow = 0; nRow < static_cast< SCROW >( nRows ); ++nRow)
+ {
+ if (pMtx->IsString(nCol, nRow))
+ {
@@ -5664,7 +6291,7 @@
{
mxImpl->Save( rStrm );
diff --git sc/source/filter/excel/xilink.cxx sc/source/filter/excel/xilink.cxx
-index 01932a5..0b79f64 100644
+index 01932a5..f906ef8 100644
--- sc/source/filter/excel/xilink.cxx
+++ sc/source/filter/excel/xilink.cxx
@@ -38,6 +38,13 @@
@@ -5805,13 +6432,15 @@
if( ::get_flag( nFlags, EXC_EXTN_BUILTIN ) || !::get_flag( nFlags, EXC_EXTN_OLE_OR_DDE ) )
{
if( bAddIn )
-@@ -319,6 +317,28 @@ XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
+@@ -319,6 +317,30 @@ XclImpExtName::XclImpExtName( XclImpStream& rStrm, bool bAddIn )
if( (meType == xlExtDDE) && (rStrm.GetRecLeft() > 1) )
mxDdeMatrix.reset( new XclImpCachedMatrix( rStrm ) );
+
+ if (meType == xlExtName)
+ {
++ // TODO: For now, only global external names are supported. In future
++ // we should extend this to supporting per-sheet external names.
+ if (mnStorageId == 0)
+ {
+ if (pFormulaConv)
@@ -5834,20 +6463,28 @@
}
XclImpExtName::~XclImpExtName()
-@@ -333,6 +353,12 @@ void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, cons
+@@ -333,6 +355,20 @@ void XclImpExtName::CreateDdeData( ScDocument& rDoc, const String& rApplic, cons
rDoc.CreateDdeLink( rApplic, rTopic, maName, SC_DDE_DEFAULT, xResults );
}
+void XclImpExtName::CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const
+{
++ if (!mxArray.get())
++ return;
++
+ ScExternalRefManager* pRefMgr = rDoc.GetExternalRefManager();
+ pRefMgr->storeRangeNameTokens(nFileId, maName, *mxArray);
+}
+
++bool XclImpExtName::HasFormulaTokens() const
++{
++ return (mxArray.get() != NULL);
++}
++
// Cached external cells ======================================================
XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
-@@ -341,29 +367,9 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
+@@ -341,29 +377,9 @@ XclImpCrn::XclImpCrn( XclImpStream& rStrm, const XclAddress& rXclPos ) :
{
}
@@ -5879,7 +6516,7 @@
}
// Sheet in an external document ==============================================
-@@ -383,13 +389,40 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
+@@ -383,13 +399,40 @@ void XclImpSupbookTab::ReadCrn( XclImpStream& rStrm, const XclAddress& rXclPos )
maCrnList.Append( new XclImpCrn( rStrm, rXclPos ) );
}
@@ -5905,7 +6542,7 @@
+ {
+ double f = p->GetValue();
+ ScExternalRefCache::TokenRef pToken(new ScDoubleToken(f));
-+ pCacheTable->setCell(rAddr.mnRow, rAddr.mnCol, pToken);
++ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
+ break;
+ case EXC_CACHEDVAL_EMPTY:
@@ -5916,7 +6553,7 @@
+ {
+ const String& rStr = p->GetString();
+ ScExternalRefCache::TokenRef pToken(new ScStringToken(rStr));
-+ pCacheTable->setCell(rAddr.mnRow, rAddr.mnCol, pToken);
++ pCacheTable->setCell(rAddr.mnCol, rAddr.mnRow, pToken);
+ }
+ break;
+ default:
@@ -5926,7 +6563,7 @@
}
// External document (SUPBOOK) ================================================
-@@ -453,25 +486,9 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
+@@ -453,25 +496,9 @@ void XclImpSupbook::ReadCrn( XclImpStream& rStrm )
}
}
@@ -5954,7 +6591,7 @@
}
const XclImpExtName* XclImpSupbook::GetExternName( sal_uInt16 nXclIndex ) const
-@@ -492,20 +509,46 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
+@@ -492,20 +519,46 @@ const String& XclImpSupbook::GetMacroName( sal_uInt16 nXclNameIdx ) const
return (pName && pName->IsVBName()) ? pName->GetScName() : EMPTY_STRING;
}
@@ -5985,33 +6622,33 @@
+{
+ if (meType != EXC_SBTYPE_EXTERN || GetExtDocOptions().GetDocSettings().mnLinkCnt > 0)
+ return;
-+
-+ String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
- // get filter name for external document
- if( !maFilterName.Len() )
- ScDocumentLoader::GetFilterName( aAbsUrl, maFilterName, maFilterOpt, FALSE, FALSE );
-+ ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
-+ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
++ String aAbsUrl( ScGlobal::GetAbsDocName(maXclUrl, GetDocShell()) );
- // create tables
- for( sal_uInt16 nSBTab = nSBTabFirst; nSBTab <= nSBTabLast; ++nSBTab )
- if( XclImpSupbookTab* pSBTab = maSupbTabList.GetObject( nSBTab ) )
- pSBTab->CreateAndFillTable( GetRoot(), aAbsUrl, maFilterName, maFilterOpt );
-+ sal_uInt16 nCount = maSupbTabList.Count();
++ ScExternalRefManager* pRefMgr = GetRoot().GetDoc().GetExternalRefManager();
++ sal_uInt16 nFileId = pRefMgr->getExternalFileId(aAbsUrl);
++
++ sal_uInt16 nCount = static_cast< sal_uInt16 >( maSupbTabList.Count() );
+ for (sal_uInt16 i = 0; i < nCount; ++i)
+ {
+ XclImpSupbookTab* pTab = maSupbTabList.GetObject(i);
+ if (!pTab)
+ return;
-+
++
+ const String& rTabName = pTab->GetTabName();
+ ScExternalRefCache::TableTypeRef pCacheTable = pRefMgr->getCacheTable(nFileId, rTabName, true);
+ pTab->LoadCachedValues(pCacheTable);
}
}
-@@ -531,7 +574,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
+@@ -531,7 +584,7 @@ void XclImpLinkManagerImpl::ReadExternsheet( XclImpStream& rStrm )
--nXtiCount;
}
@@ -6020,7 +6657,7 @@
}
void XclImpLinkManagerImpl::ReadSupbook( XclImpStream& rStrm )
-@@ -551,10 +594,10 @@ void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
+@@ -551,10 +604,10 @@ void XclImpLinkManagerImpl::ReadCrn( XclImpStream& rStrm )
pSupbook->ReadCrn( rStrm );
}
@@ -6033,7 +6670,7 @@
}
bool XclImpLinkManagerImpl::IsSelfRef( sal_uInt16 nXtiIndex ) const
-@@ -568,10 +611,10 @@ bool XclImpLinkManagerImpl::GetScTabRange(
+@@ -568,10 +621,10 @@ bool XclImpLinkManagerImpl::GetScTabRange(
{
if( const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex ) )
{
@@ -6047,7 +6684,7 @@
return true;
}
}
-@@ -584,6 +627,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
+@@ -584,6 +637,20 @@ const XclImpExtName* XclImpLinkManagerImpl::GetExternName( sal_uInt16 nXtiIndex,
return pSupbook ? pSupbook->GetExternName( nExtName ) : 0;
}
@@ -6068,7 +6705,7 @@
bool XclImpLinkManagerImpl::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
{
const XclImpSupbook* pSupbook = GetSupbook( nXtiIndex );
-@@ -596,12 +653,6 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
+@@ -596,12 +663,6 @@ const String& XclImpLinkManagerImpl::GetMacroName( sal_uInt16 nExtSheet, sal_uIn
return pSupbook ? pSupbook->GetMacroName( nExtName ) : EMPTY_STRING;
}
@@ -6081,7 +6718,7 @@
const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( sal_uInt32 nXtiIndex ) const
{
const XclImpXti* pXti = maXtiList.GetObject( nXtiIndex );
-@@ -616,26 +667,17 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
+@@ -616,26 +677,17 @@ const XclImpSupbook* XclImpLinkManagerImpl::GetSupbook( const String& rUrl ) con
return 0;
}
@@ -6090,7 +6727,7 @@
{
- DBG_ASSERT( !mbCreated, "XclImpLinkManager::CreateTables - multiple call" );
- if( mbCreated ) return;
-+ // Read all CRN records which can be accessed via XclImpSupbook, and store
++ // Read all CRN records which can be accessed via XclImpSupbook, and store
+ // the cached values to the external reference manager.
- sal_uInt16 nSBTabFirst, nSBTabLast;
@@ -6114,7 +6751,7 @@
}
bool XclImpLinkManagerImpl::FindNextTabRange(
-@@ -686,9 +728,9 @@ void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
+@@ -686,9 +738,9 @@ void XclImpLinkManager::ReadCrn( XclImpStream& rStrm )
mxImpl->ReadCrn( rStrm );
}
@@ -6126,7 +6763,7 @@
}
bool XclImpLinkManager::IsSelfRef( sal_uInt16 nXtiIndex ) const
-@@ -707,6 +749,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
+@@ -707,6 +759,16 @@ const XclImpExtName* XclImpLinkManager::GetExternName( sal_uInt16 nXtiIndex, sal
return mxImpl->GetExternName( nXtiIndex, nExtName );
}
@@ -6143,7 +6780,7 @@
bool XclImpLinkManager::GetLinkData( String& rApplic, String& rTopic, sal_uInt16 nXtiIndex ) const
{
return mxImpl->GetLinkData( rApplic, rTopic, nXtiIndex );
-@@ -717,10 +769,5 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
+@@ -717,10 +779,5 @@ const String& XclImpLinkManager::GetMacroName( sal_uInt16 nExtSheet, sal_uInt16
return mxImpl->GetMacroName( nExtSheet, nExtName );
}
@@ -6382,7 +7019,7 @@
virtual void Save( XclExpStream& rStrm );
diff --git sc/source/filter/inc/xilink.hxx sc/source/filter/inc/xilink.hxx
-index 0d547fe..3983e4d 100644
+index 0d547fe..8b74794 100644
--- sc/source/filter/inc/xilink.hxx
+++ sc/source/filter/inc/xilink.hxx
@@ -107,6 +107,8 @@ enum XclImpExtNameType
@@ -6394,7 +7031,7 @@
/** Stores contents of an external name.
@descr Supported: External defined names, AddIn names, DDE links and OLE objects. */
-@@ -114,21 +116,26 @@ class XclImpExtName
+@@ -114,21 +116,28 @@ class XclImpExtName
{
public:
/** Reads the external name from the stream. */
@@ -6409,6 +7046,8 @@
+ void CreateExtNameData( ScDocument& rDoc, sal_uInt16 nFileId ) const;
+
++ bool HasFormulaTokens() const;
++
inline XclImpExtNameType GetType() const { return meType; }
inline const String& GetName() const { return maName; }
inline sal_uInt32 GetStorageId() const { return mnStorageId; }
@@ -6422,7 +7061,7 @@
String maName; /// The name of the external name.
sal_uInt32 mnStorageId; /// Storage ID for OLE object storages.
XclImpExtNameType meType; /// Type of the external name.
-@@ -168,7 +175,7 @@ public:
+@@ -168,7 +177,7 @@ public:
/** Reads a CRN record and appends it to the current SUPBOOK. */
void ReadCrn( XclImpStream& rStrm );
/** Reads an EXTERNNAME record and appends it to the current SUPBOOK. */
@@ -6431,7 +7070,7 @@
/** Returns true, if the specified XTI entry contains an internal reference. */
bool IsSelfRef( sal_uInt16 nXtiIndex ) const;
-@@ -179,6 +186,11 @@ public:
+@@ -179,6 +188,11 @@ public:
sal_uInt16 nXtiIndex ) const;
/** Returns the specified external name or 0 on error. */
const XclImpExtName* GetExternName( sal_uInt16 nXtiIndex, sal_uInt16 nExtName ) const;
@@ -6443,7 +7082,7 @@
/** Tries to decode the URL of the specified XTI entry to OLE or DDE link components.
@descr For DDE links: Decodes to application name and topic.
For OLE object links: Decodes to class name and document URL.
-@@ -187,10 +199,6 @@ public:
+@@ -187,10 +201,6 @@ public:
/** Returns the specified macro name or an empty string on error. */
const String& GetMacroName( sal_uInt16 nExtSheet, sal_uInt16 nExtName ) const;
@@ -6530,7 +7169,7 @@
//------------------------------------------------------------------
diff --git sc/source/filter/xml/XMLTableShapeImportHelper.cxx sc/source/filter/xml/XMLTableShapeImportHelper.cxx
-index bb6fe74..219b5cc 100644
+index 57e5464..25f47f9 100644
--- sc/source/filter/xml/XMLTableShapeImportHelper.cxx
+++ sc/source/filter/xml/XMLTableShapeImportHelper.cxx
@@ -49,6 +49,7 @@
@@ -6586,7 +7225,7 @@
//------------------------------------------------------------------
diff --git sc/source/filter/xml/xmlcelli.cxx sc/source/filter/xml/xmlcelli.cxx
-index 92eb208..a990e54 100644
+index 4788cd1..d8e9363 100644
--- sc/source/filter/xml/xmlcelli.cxx
+++ sc/source/filter/xml/xmlcelli.cxx
@@ -146,185 +146,131 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport,
@@ -6929,7 +7568,7 @@
const sal_Int32 nCol, const sal_Int32 nRow,
com::sun::star::table::CellRangeAddress& aCellAddress) const;
diff --git sc/source/filter/xml/xmldpimp.cxx sc/source/filter/xml/xmldpimp.cxx
-index e29223a..604e04e 100644
+index 2129837..8c8e895 100644
--- sc/source/filter/xml/xmldpimp.cxx
+++ sc/source/filter/xml/xmldpimp.cxx
@@ -65,6 +65,7 @@
@@ -6941,7 +7580,7 @@
//------------------------------------------------------------------
diff --git sc/source/filter/xml/xmlexprt.cxx sc/source/filter/xml/xmlexprt.cxx
-index 441f463..119a53f 100644
+index b29578f..155cc6d 100644
--- sc/source/filter/xml/xmlexprt.cxx
+++ sc/source/filter/xml/xmlexprt.cxx
@@ -68,6 +68,7 @@
@@ -6982,7 +7621,82 @@
sAttrName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NAME));
sAttrStyleName = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_STYLE_NAME));
sAttrColumnsRepeated = GetNamespaceMap().GetQNameByKey( XML_NAMESPACE_TABLE, GetXMLToken(XML_NUMBER_COLUMNS_REPEATED));
-@@ -1422,180 +1432,181 @@ void ScXMLExport::_ExportContent()
+@@ -525,6 +535,15 @@ ScXMLExport::~ScXMLExport()
+ delete pNumberFormatAttributesExportHelper;
+ }
+
++sal_Int32 ScXMLExport::GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const
++{
++ NumberFormatIndexMap::const_iterator itr = aNumFmtIndexMap.find(nNumFmt);
++ if (itr == aNumFmtIndexMap.end())
++ return -1;
++
++ return itr->second;
++}
++
+ sal_Bool ScXMLExport::HasDrawPages(uno::Reference <sheet::XSpreadsheetDocument>& xDoc)
+ {
+ uno::Reference <beans::XPropertySet> xDocProps( xDoc, uno::UNO_QUERY );
+@@ -1019,6 +1038,58 @@ void ScXMLExport::ExportColumns(const sal_Int32 nTable, const table::CellRangeAd
+ pGroupColumns->CloseGroups(nColumn - 1);
+ }
+
++void ScXMLExport::ExportExternalRefCacheStyles()
++{
++ sal_Int32 nEntryIndex = GetCellStylesPropertySetMapper()->FindEntryIndex(
++ "NumberFormat", XML_NAMESPACE_STYLE, OUString::createFromAscii("data-style-name"));
++
++ if (nEntryIndex < 0)
++ // No entry index for the number format is found.
++ return;
++
++ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
++ if (!pRefMgr->hasExternalData())
++ // No external reference data cached.
++ return;
++
++ // Export each unique number format used in the external ref cache.
++ vector<sal_uInt32> aNumFmts;
++ pRefMgr->getAllCachedNumberFormats(aNumFmts);
++ const OUString aDefaultStyle = OUString::createFromAscii("Default").intern();
++ for (vector<sal_uInt32>::const_iterator itr = aNumFmts.begin(), itrEnd = aNumFmts.end();
++ itr != itrEnd; ++itr)
++ {
++ sal_Int32 nNumFmt = static_cast<sal_Int32>(*itr);
++
++ addDataStyle(nNumFmt);
++
++ uno::Any aVal;
++ aVal <<= nNumFmt;
++ vector<XMLPropertyState> aProps;
++ aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
++ aVal <<= aDefaultStyle;
++ aProps.push_back(XMLPropertyState(nEntryIndex, aVal));
++
++ OUString aName;
++ sal_Int32 nIndex;
++ if (GetAutoStylePool()->Add(aName, XML_STYLE_FAMILY_TABLE_CELL, aDefaultStyle, aProps))
++ {
++ OUString* pTemp(new OUString(aName));
++ if (!pCellStyles->AddStyleName(pTemp, nIndex, true))
++ delete pTemp;
++ }
++ else
++ {
++ sal_Bool bIsAuto;
++ nIndex = pCellStyles->GetIndexOfStyleName(
++ aName, OUString::createFromAscii(XML_STYLE_FAMILY_TABLE_CELL_STYLES_PREFIX), bIsAuto);
++ }
++
++ // store the number format to index mapping for later use.
++ aNumFmtIndexMap.insert(NumberFormatIndexMap::value_type(nNumFmt, nIndex));
++ }
++}
++
+ void ScXMLExport::WriteRowContent()
+ {
+ ScMyRowFormatRange aRange;
+@@ -1422,180 +1493,181 @@ void ScXMLExport::_ExportContent()
DBG_ERROR("no shared data setted");
}
ScXMLExportDatabaseRanges aExportDatabaseRanges(*this);
@@ -7330,7 +8044,16 @@
}
void ScXMLExport::_ExportStyles( sal_Bool bUsed )
-@@ -2000,6 +2011,15 @@ void ScXMLExport::_ExportAutoStyles()
+@@ -1671,6 +1743,8 @@ void ScXMLExport::_ExportAutoStyles()
+ {
+ if (getExportFlags() & EXPORT_CONTENT)
+ {
++ ExportExternalRefCacheStyles();
++
+ if (!pSharedData)
+ {
+ sal_Int32 nTableCount(0);
+@@ -2000,6 +2074,15 @@ void ScXMLExport::_ExportAutoStyles()
GetShapeExport()->exportAutoStyles();
GetFormExport()->exportAutoStyles( );
@@ -7346,7 +8069,16 @@
}
if (getExportFlags() & EXPORT_MASTERSTYLES)
{
-@@ -3333,6 +3353,184 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
+@@ -3003,7 +3086,7 @@ sal_Bool ScXMLExport::IsCellEqual (ScMyCell& aCell1, ScMyCell& aCell2)
+ }
+ // #i29101# number format may be different from column default styles,
+ // but can lead to different value types, so it must also be compared
+- bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
++ bIsEqual = (aCell1.nNumberFormat == aCell2.nNumberFormat) &&
+ (aCell1.fValue == aCell2.fValue);
+ }
+ break;
+@@ -3344,6 +3427,192 @@ void ScXMLExport::WriteNamedExpressions(const com::sun::star::uno::Reference <co
}
}
@@ -7357,7 +8089,7 @@
+
+ ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
+ pRefMgr->resetSrcFileData();
-+ sal_uInt16 nCount = pRefMgr->getCachedFileCount();
++ sal_uInt16 nCount = pRefMgr->getExternalFileCount();
+ for (sal_uInt16 nFileId = 0; nFileId < nCount; ++nFileId)
+ {
+ const String* pUrl = pRefMgr->getExternalFileName(nFileId);
@@ -7418,7 +8150,7 @@
+ if (bFirstRow)
+ {
+ if (nRow > 0)
-+ {
++ {
+ if (nRow > 1)
+ {
+ OUStringBuffer aVal;
@@ -7463,7 +8195,7 @@
+ if (bFirstCol)
+ {
+ if (nCol > 0)
-+ {
++ {
+ if (nCol > 1)
+ {
+ OUStringBuffer aVal;
@@ -7489,10 +8221,18 @@
+ }
+
+ // Write out this cell.
-+ ScExternalRefCache::TokenRef pToken = pTable->getCell(nRow, nCol);
++ sal_uInt32 nNumFmt = 0;
++ ScExternalRefCache::TokenRef pToken = pTable->getCell(nCol, nRow, &nNumFmt);
+ OUString aStrVal;
+ if (pToken.get())
+ {
++ sal_Int32 nIndex = GetNumberFormatStyleIndex(nNumFmt);
++ if (nIndex >= 0)
++ {
++ const OUString aStyleName = *pCellStyles->GetStyleNameByIndex(nIndex, true);
++ AddAttribute(XML_NAMESPACE_TABLE, XML_STYLE_NAME, aStyleName);
++ }
++
+ switch(pToken->GetType())
+ {
+ case svDouble:
@@ -7532,10 +8272,28 @@
void ScXMLExport::WriteConsolidation()
{
diff --git sc/source/filter/xml/xmlexprt.hxx sc/source/filter/xml/xmlexprt.hxx
-index 47171b6..e8477e5 100644
+index e4fcc10..a6385f1 100644
--- sc/source/filter/xml/xmlexprt.hxx
+++ sc/source/filter/xml/xmlexprt.hxx
-@@ -98,6 +98,7 @@ class ScXMLExport : public SvXMLExport
+@@ -38,6 +38,8 @@
+ #include <com/sun/star/drawing/XShapes.hpp>
+ #include <com/sun/star/table/XCellRange.hpp>
+
++#include <hash_map>
++
+ class ScOutlineArray;
+ class SvXMLExportPropertyMapper;
+ class ScMyShapesContainer;
+@@ -80,6 +82,8 @@ class ScXMLExport : public SvXMLExport
+ UniReference < SvXMLExportPropertyMapper > xRowStylesExportPropertySetMapper;
+ UniReference < SvXMLExportPropertyMapper > xTableStylesExportPropertySetMapper;
+ XMLNumberFormatAttributesExportHelper* pNumberFormatAttributesExportHelper;
++ typedef ::std::hash_map<sal_Int32, sal_Int32> NumberFormatIndexMap;
++ NumberFormatIndexMap aNumFmtIndexMap;
+ ScMySharedData* pSharedData;
+ ScColumnStyles* pColumnStyles;
+ ScRowStyles* pRowStyles;
+@@ -99,6 +103,7 @@ class ScXMLExport : public SvXMLExport
ScChangeTrackingExportHelper* pChangeTrackingExportHelper;
const rtl::OUString sLayerID;
const rtl::OUString sCaptionShape;
@@ -7543,7 +8301,24 @@
rtl::OUString sAttrName;
rtl::OUString sAttrStyleName;
rtl::OUString sAttrColumnsRepeated;
-@@ -195,6 +196,7 @@ class ScXMLExport : public SvXMLExport
+@@ -118,7 +123,7 @@ class ScXMLExport : public SvXMLExport
+ sal_Bool bRowHeaderOpen;
+ sal_Bool mbShowProgress;
+
+-
++ sal_Int32 GetNumberFormatStyleIndex(sal_Int32 nNumFmt) const;
+ sal_Bool HasDrawPages(com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xDoc);
+ void CollectSharedData(sal_Int32& nTableCount, sal_Int32& nShapesCount, const sal_Int32 nCellCount);
+ void CollectShapesAutoStyles(const sal_Int32 nTableCount);
+@@ -146,6 +151,7 @@ class ScXMLExport : public SvXMLExport
+ void OpenHeaderColumn();
+ void CloseHeaderColumn();
+ void ExportColumns(const sal_Int32 nTable, const com::sun::star::table::CellRangeAddress& aColumnHeaderRange, const sal_Bool bHasColumnHeader);
++ void ExportExternalRefCacheStyles();
+ void ExportFormatRanges(const sal_Int32 nStartCol, const sal_Int32 nStartRow,
+ const sal_Int32 nEndCol, const sal_Int32 nEndRow, const sal_Int32 nSheet);
+ void WriteRowContent();
+@@ -196,6 +202,7 @@ class ScXMLExport : public SvXMLExport
void WriteTheLabelRanges(const com::sun::star::uno::Reference< com::sun::star::sheet::XSpreadsheetDocument >& xSpreadDoc);
void WriteLabelRanges( const com::sun::star::uno::Reference< com::sun::star::container::XIndexAccess >& xRangesIAccess, sal_Bool bColumn );
void WriteNamedExpressions(const com::sun::star::uno::Reference <com::sun::star::sheet::XSpreadsheetDocument>& xSpreadDoc);
@@ -7553,10 +8328,10 @@
void CollectUserDefinedNamespaces(const SfxItemPool* pPool, sal_uInt16 nAttrib);
diff --git sc/source/filter/xml/xmlexternaltabi.cxx sc/source/filter/xml/xmlexternaltabi.cxx
new file mode 100644
-index 0000000..3417206
+index 0000000..f4e42be
--- /dev/null
+++ sc/source/filter/xml/xmlexternaltabi.cxx
-@@ -0,0 +1,343 @@
+@@ -0,0 +1,355 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -7597,6 +8372,7 @@
+#include "xmlexternaltabi.hxx"
+#include "xmlimprt.hxx"
+#include "xmltabi.hxx"
++#include "xmlstyli.hxx"
+
+#include "token.hxx"
+#include "document.hxx"
@@ -7616,10 +8392,10 @@
+// ============================================================================
+
+ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
-+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
-+ mrScImport(rImport),
++ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo)
+{
+ using namespace ::xmloff::token;
@@ -7673,10 +8449,10 @@
+// ============================================================================
+
+ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
-+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
-+ mrScImport(rImport),
++ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo),
+ mnRepeatRowCount(1)
+{
@@ -7726,12 +8502,12 @@
+ for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
+ {
+ ScExternalRefCache::TokenRef pToken = pTab->getCell(
-+ static_cast<SCROW>(mrExternalRefInfo.mnRow), static_cast<SCCOL>(j));
++ static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
+
+ if (pToken.get())
+ {
-+ pTab->setCell(static_cast<SCROW>(
-+ mrExternalRefInfo.mnRow+i), static_cast<SCCOL>(j), pToken);
++ pTab->setCell(static_cast<SCCOL>(j),
++ static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
+ }
+ }
+ }
@@ -7741,13 +8517,14 @@
+// ============================================================================
+
+ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
-+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
-+ mrScImport(rImport),
++ mrScImport(rImport),
+ mrExternalRefInfo(rRefInfo),
+ mfCellValue(0.0),
+ mnRepeatCount(1),
++ mnNumberFormat(-1),
+ mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
+ mbIsNumeric(false),
+ mbIsEmpty(true)
@@ -7767,8 +8544,17 @@
+
+ switch (nToken)
+ {
++ case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
++ {
++ XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
++ const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
++ pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
++ if (pStyle)
++ mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
++ }
++ break;
+ case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
-+ {
++ {
+ mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
+ }
+ break;
@@ -7864,20 +8650,21 @@
+ else
+ aToken.reset(new ScStringToken(maCellString));
+
++ sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
+ mrExternalRefInfo.mpCacheTable->setCell(
-+ static_cast<SCROW>(mrExternalRefInfo.mnRow),
-+ static_cast<SCCOL>(mrExternalRefInfo.mnCol),
-+ aToken);
++ static_cast<SCCOL>(mrExternalRefInfo.mnCol),
++ static_cast<SCROW>(mrExternalRefInfo.mnRow),
++ aToken, nNumFmt);
+ }
+}
+
+// ============================================================================
+
+ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
-+ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
++ ScXMLImport& rImport, USHORT nPrefix, const OUString& rLName,
+ const Reference<XAttributeList>& /*xAttrList*/, OUString& rCellString ) :
+ SvXMLImportContext( rImport, nPrefix, rLName ),
-+ mrScImport(rImport),
++ mrScImport(rImport),
+ mrCellString(rCellString)
+{
+}
@@ -7902,10 +8689,10 @@
+}
diff --git sc/source/filter/xml/xmlexternaltabi.hxx sc/source/filter/xml/xmlexternaltabi.hxx
new file mode 100644
-index 0000000..6f26789
+index 0000000..2c3f3fb
--- /dev/null
+++ sc/source/filter/xml/xmlexternaltabi.hxx
-@@ -0,0 +1,149 @@
+@@ -0,0 +1,150 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -8022,6 +8809,7 @@
+ ::rtl::OUString maCellString;
+ double mfCellValue;
+ sal_Int32 mnRepeatCount;
++ sal_Int32 mnNumberFormat;
+ sal_Int16 mnCellType;
+ bool mbIsNumeric;
+ bool mbIsEmpty;
@@ -8056,7 +8844,7 @@
+
+#endif
diff --git sc/source/filter/xml/xmlimprt.cxx sc/source/filter/xml/xmlimprt.cxx
-index 47b26b9..eb74c99 100644
+index c21e3ca..2d876ed 100644
--- sc/source/filter/xml/xmlimprt.cxx
+++ sc/source/filter/xml/xmlimprt.cxx
@@ -104,6 +104,7 @@
@@ -8196,7 +8984,7 @@
// inline const SvXMLImportItemMapper& GetParaItemMapper() const;
diff --git sc/source/filter/xml/xmlsceni.cxx sc/source/filter/xml/xmlsceni.cxx
-index cfe859d..f4d6c89 100644
+index 6165d6a..586176f 100644
--- sc/source/filter/xml/xmlsceni.cxx
+++ sc/source/filter/xml/xmlsceni.cxx
@@ -50,6 +50,7 @@
@@ -8208,7 +8996,7 @@
//------------------------------------------------------------------
diff --git sc/source/filter/xml/xmlstyle.cxx sc/source/filter/xml/xmlstyle.cxx
-index 7aec632..863e82c 100644
+index 9385621..e64fd22 100644
--- sc/source/filter/xml/xmlstyle.cxx
+++ sc/source/filter/xml/xmlstyle.cxx
@@ -65,6 +65,7 @@
@@ -8232,8 +9020,89 @@
extern const XMLPropertyMapEntry aXMLScCellStylesProperties[];
extern const XMLPropertyMapEntry aXMLScColumnStylesProperties[];
extern const XMLPropertyMapEntry aXMLScRowStylesProperties[];
+diff --git sc/source/filter/xml/xmlstyli.cxx sc/source/filter/xml/xmlstyli.cxx
+index 6813d0d..9624740 100644
+--- sc/source/filter/xml/xmlstyli.cxx
++++ sc/source/filter/xml/xmlstyli.cxx
+@@ -584,28 +584,10 @@ void XMLTableStyleContext::FillPropertySet(
+ AddProperty(CTF_SC_CELLSTYLE, uno::makeAny(GetImport().GetStyleDisplayName( XML_STYLE_FAMILY_TABLE_CELL, GetParentName() )));
+ bParentSet = sal_True;
+ }
+- if ((nNumberFormat == -1) && sDataStyleName.getLength())
+- {
+- SvXMLNumFormatContext* pStyle((SvXMLNumFormatContext *)pStyles->FindStyleChildContext(
+- XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
+- if (!pStyle)
+- {
+- XMLTableStylesContext* pMyStyles((XMLTableStylesContext *)GetScImport().GetStyles());
+- if (pMyStyles)
+- pStyle = (SvXMLNumFormatContext *)pMyStyles->
+- FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True);
+- else
+- {
+- DBG_ERROR("not possible to get style");
+- }
+- }
+- if (pStyle)
+- {
+- //rPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_NUMBERFORMAT)), aNumberFormat);
+- nNumberFormat = pStyle->GetKey();
+- AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumberFormat));
+- }
+- }
++ sal_Int32 nNumFmt = GetNumberFormat();
++ if (nNumFmt >= 0)
++ AddProperty(CTF_SC_NUMBERFORMAT, uno::makeAny(nNumFmt));
++
+ if (!bConditionalFormatCreated && (aMaps.size() > 0))
+ {
+ aConditionalFormat = rPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_CONDXML)));
+@@ -683,6 +665,30 @@ XMLPropertyState* XMLTableStyleContext::FindProperty(const sal_Int16 nContextID)
+ return pRet;
+ }
+
++sal_Int32 XMLTableStyleContext::GetNumberFormat()
++{
++ if (nNumberFormat < 0 && sDataStyleName.getLength())
++ {
++ const SvXMLNumFormatContext* pStyle = static_cast<const SvXMLNumFormatContext*>(
++ pStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
++
++ if (!pStyle)
++ {
++ XMLTableStylesContext* pMyStyles = static_cast<XMLTableStylesContext*>(GetScImport().GetStyles());
++ if (pMyStyles)
++ pStyle = static_cast<const SvXMLNumFormatContext*>(
++ pMyStyles->FindStyleChildContext(XML_STYLE_FAMILY_DATA_STYLE, sDataStyleName, sal_True));
++ else
++ {
++ DBG_ERROR("not possible to get style");
++ }
++ }
++ if (pStyle)
++ nNumberFormat = const_cast<SvXMLNumFormatContext*>(pStyle)->GetKey();
++ }
++ return nNumberFormat;
++}
++
+ // ----------------------------------------------------------------------------
+
+ SvXMLStyleContext *XMLTableStylesContext::CreateStyleStyleChildContext(
+diff --git sc/source/filter/xml/xmlstyli.hxx sc/source/filter/xml/xmlstyli.hxx
+index d1d6166..237e8e3 100644
+--- sc/source/filter/xml/xmlstyli.hxx
++++ sc/source/filter/xml/xmlstyli.hxx
+@@ -154,7 +154,7 @@ public:
+ void AddProperty(sal_Int16 nContextID, const com::sun::star::uno::Any& aValue);
+ XMLPropertyState* FindProperty(const sal_Int16 nContextID);
+
+- sal_Int32 GetNumberFormat() { return nNumberFormat; }
++ sal_Int32 GetNumberFormat();
+
+ private:
+ using XMLPropStyleContext::SetStyle;
diff --git sc/source/filter/xml/xmltabi.cxx sc/source/filter/xml/xmltabi.cxx
-index 4a0f83e..4dd5a55 100644
+index 6d23650..9137f0f 100644
--- sc/source/filter/xml/xmltabi.cxx
+++ sc/source/filter/xml/xmltabi.cxx
@@ -40,6 +40,7 @@
@@ -8454,7 +9323,7 @@
// -----------------------------------------------------------------------
diff --git sc/source/ui/docshell/docsh4.cxx sc/source/ui/docshell/docsh4.cxx
-index bc5975d..6701d1c 100644
+index 4894362..857a0dd 100644
--- sc/source/ui/docshell/docsh4.cxx
+++ sc/source/ui/docshell/docsh4.cxx
@@ -123,6 +123,7 @@ using namespace ::com::sun::star;
@@ -8475,10 +9344,10 @@
diff --git sc/source/ui/docshell/externalrefmgr.cxx sc/source/ui/docshell/externalrefmgr.cxx
new file mode 100644
-index 0000000..20dd943
+index 0000000..9dcb2cc
--- /dev/null
+++ sc/source/ui/docshell/externalrefmgr.cxx
-@@ -0,0 +1,1398 @@
+@@ -0,0 +1,1888 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -8541,6 +9410,7 @@
+#include "svtools/itemset.hxx"
+#include "svtools/stritem.hxx"
+#include "svtools/urihelper.hxx"
++#include "svtools/zformat.hxx"
+#include "svx/linkmgr.hxx"
+#include "tools/urlobj.hxx"
+#include "unotools/ucbhelper.hxx"
@@ -8553,44 +9423,89 @@
+using ::rtl::OUString;
+using ::std::vector;
+using ::std::find;
++using ::std::find_if;
+using ::std::distance;
++using ::std::pair;
++using ::std::list;
+
+#define SRCDOC_LIFE_SPAN 6000 // 1 minute (in 100th of a sec)
+#define SRCDOC_SCAN_INTERVAL 1000*5 // every 5 seconds (in msec)
+
-+// ============================================================================
-+
-+ScExternalRefCache::Table::Table()
-+{
-+}
-+
-+ScExternalRefCache::Table::~Table()
-+{
-+}
++namespace {
+
-+void ScExternalRefCache::Table::setCell(SCROW nRow, SCCOL nCol, TokenRef pToken)
++class TabNameSearchPredicate : ::std::unary_function<bool, ScExternalRefCache::TableName>
+{
-+ using ::std::pair;
-+ RowsDataType::iterator itrRow = maRows.find(nRow);
-+ if (itrRow == maRows.end())
++public:
++ explicit TabNameSearchPredicate(const String& rSearchName) :
++ maSearchName(ScGlobal::pCharClass->upper(rSearchName))
+ {
-+ // This row does not exist yet.
-+ pair<RowsDataType::iterator, bool> res = maRows.insert(
-+ RowsDataType::value_type(nRow, RowDataType()));
-+
-+ if (!res.second)
-+ return;
++ }
+
-+ itrRow = res.first;
++ bool operator()(const ScExternalRefCache::TableName& rTabNameSet) const
++ {
++ // Ok, I'm doing case insensitive search here.
++ return rTabNameSet.maUpperName.Equals(maSearchName);
+ }
+
-+ // Insert this token into the specified column location. I don't need to
-+ // check for existing data. Just overwrite it.
-+ RowDataType& rRow = itrRow->second;
-+ rRow.insert(RowDataType::value_type(nCol, pToken));
++private:
++ String maSearchName;
++};
++
++class FindSrcFileByName : public ::std::unary_function<ScExternalRefManager::SrcFileData, bool>
++{
++public:
++ FindSrcFileByName(const String& rMatchName) :
++ mrMatchName(rMatchName)
++ {
++ }
++
++ bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
++ {
++ return rSrcData.maFileName.Equals(mrMatchName);
++ }
++
++private:
++ const String& mrMatchName;
++};
++
++}
++
++// ============================================================================
++
++ScExternalRefCache::Table::Table()
++{
++}
++
++ScExternalRefCache::Table::~Table()
++{
+}
+
-+ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCROW nRow, SCCOL nCol) const
++void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex)
++{
++ using ::std::pair;
++ RowsDataType::iterator itrRow = maRows.find(nRow);
++ if (itrRow == maRows.end())
++ {
++ // This row does not exist yet.
++ pair<RowsDataType::iterator, bool> res = maRows.insert(
++ RowsDataType::value_type(nRow, RowDataType()));
++
++ if (!res.second)
++ return;
++
++ itrRow = res.first;
++ }
++
++ // Insert this token into the specified column location. I don't need to
++ // check for existing data. Just overwrite it.
++ RowDataType& rRow = itrRow->second;
++ ScExternalRefCache::Cell aCell;
++ aCell.mxToken = pToken;
++ aCell.mnFmtIndex = nFmtIndex;
++ rRow.insert(RowDataType::value_type(nCol, aCell));
++}
++
++ScExternalRefCache::TokenRef ScExternalRefCache::Table::getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex) const
+{
+ RowsDataType::const_iterator itrTable = maRows.find(nRow);
+ if (itrTable == maRows.end())
@@ -8607,7 +9522,11 @@
+ return TokenRef();
+ }
+
-+ return itrRow->second;
++ const Cell& rCell = itrRow->second;
++ if (pnFmtIndex)
++ *pnFmtIndex = rCell.mnFmtIndex;
++
++ return rCell.mxToken;
+}
+
+void ScExternalRefCache::Table::getAllRows(vector<SCROW>& rRows) const
@@ -8642,6 +9561,21 @@
+ rCols.swap(aCols);
+}
+
++void ScExternalRefCache::Table::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++ RowsDataType::const_iterator itrRow = maRows.begin(), itrRowEnd = maRows.end();
++ for (; itrRow != itrRowEnd; ++itrRow)
++ {
++ const RowDataType& rRowData = itrRow->second;
++ RowDataType::const_iterator itrCol = rRowData.begin(), itrColEnd = rRowData.end();
++ for (; itrCol != itrColEnd; ++itrCol)
++ {
++ const Cell& rCell = itrCol->second;
++ rNumFmts.push_back(rCell.mnFmtIndex);
++ }
++ }
++}
++
+// ----------------------------------------------------------------------------
+
+ScExternalRefCache::TableName::TableName(const String& rUpper, const String& rReal) :
@@ -8651,6 +9585,13 @@
+
+// ----------------------------------------------------------------------------
+
++ScExternalRefCache::CellFormat::CellFormat() :
++ mbIsSet(false), mnType(NUMBERFORMAT_ALL), mnIndex(0)
++{
++}
++
++// ----------------------------------------------------------------------------
++
+ScExternalRefCache::ScExternalRefCache()
+{
+}
@@ -8698,7 +9639,8 @@
+ return &itr->second;
+}
+
-+ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol)
++ScExternalRefCache::TokenRef ScExternalRefCache::getCellData(
++ sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, sal_uInt32* pnFmtIndex)
+{
+ DocDataType::const_iterator itrDoc = maDocs.find(nFileId);
+ if (itrDoc == maDocs.end())
@@ -8722,7 +9664,7 @@
+ // the table data is not instantiated yet.
+ return TokenRef();
+ }
-+ return pTableData->getCell(nRow, nCol);
++ return pTableData->getCell(nCol, nRow, pnFmtIndex);
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefCache::getCellRangeData(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange)
@@ -8774,7 +9716,7 @@
+ {
+ for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+ {
-+ ScToken* pToken = pTab->getCell(nRow, nCol).get();
++ ScToken* pToken = pTab->getCell(nCol, nRow).get();
+ if (!pToken)
+ return TokenArrayRef();
+
@@ -8833,7 +9775,8 @@
+ pDoc->maRealRangeNameMap.insert(NamePairMap::value_type(aUpperName, rName));
+}
+
-+void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol, TokenRef pToken)
++void ScExternalRefCache::setCellData(sal_uInt16 nFileId, const String& rTabName, SCROW nRow, SCCOL nCol,
++ TokenRef pToken, sal_uInt32 nFmtIndex)
+{
+ if (!isDocInitialized(nFileId))
+ return;
@@ -8844,7 +9787,7 @@
+ return;
+
+ DocItem& rDoc = *pDocItem;
-+
++
+ // See if the table by this name already exists.
+ TableNameIndexMap::iterator itrTabName = rDoc.maTableNameIndex.find(
+ ScGlobal::pCharClass->upper(rTabName));
@@ -8856,7 +9799,7 @@
+ if (!pTableData.get())
+ pTableData.reset(new Table);
+
-+ pTableData->setCell(nRow, nCol, pToken);
++ pTableData->setCell(nCol, nRow, pToken, nFmtIndex);
+}
+
+void ScExternalRefCache::setCellRangeData(sal_uInt16 nFileId, const ScRange& rRange, const vector<SingleRangeData>& rData,
@@ -8909,7 +9852,7 @@
+ else
+ pToken.reset(new ScEmptyCellToken(false, false));
+
-+ pTabData->setCell(nRow, nCol, pToken);
++ pTabData->setCell(nCol, nRow, pToken);
+ }
+ }
+ }
@@ -8944,7 +9887,7 @@
+
+ size_t n = rTabNames.size();
+
-+ // table name list - the list must include all table names in the source
++ // table name list - the list must include all table names in the source
+ // document and only to be populated when loading the source document, not
+ // when loading cached data from, say, Excel XCT/CRN records.
+ vector<TableName> aNewTabNames;
@@ -8956,8 +9899,8 @@
+ aNewTabNames.push_back(aNameItem);
+ }
+ pDoc->maTableNames.swap(aNewTabNames);
-+
-+ // data tables - preserve any existing data that may have been set during
++
++ // data tables - preserve any existing data that may have been set during
+ // file import.
+ vector<TableTypeRef> aNewTables(n);
+ for (size_t i = 0; i < n; ++i)
@@ -8979,6 +9922,14 @@
+ pDoc->mbInitFromSource = true;
+}
+
++String ScExternalRefCache::getTableName(sal_uInt16 nFileId, size_t nCacheId) const
++{
++ if( DocItem* pDoc = getDocItem( nFileId ) )
++ if( nCacheId < pDoc->maTableNames.size() )
++ return pDoc->maTableNames[ nCacheId ].maRealName;
++ return EMPTY_STRING;
++}
++
+void ScExternalRefCache::getAllTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
+{
+ rTabNames.clear();
@@ -8993,7 +9944,63 @@
+ rTabNames.push_back(itr->maRealName);
+}
+
-+ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
++void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++ using ::std::sort;
++ using ::std::unique;
++
++ vector<sal_uInt32> aNumFmts;
++ for (DocDataType::const_iterator itrDoc = maDocs.begin(), itrDocEnd = maDocs.end();
++ itrDoc != itrDocEnd; ++itrDoc)
++ {
++ const vector<TableTypeRef>& rTables = itrDoc->second.maTables;
++ for (vector<TableTypeRef>::const_iterator itrTab = rTables.begin(), itrTabEnd = rTables.end();
++ itrTab != itrTabEnd; ++itrTab)
++ {
++ TableTypeRef pTab = *itrTab;
++ if (!pTab)
++ continue;
++
++ pTab->getAllNumberFormats(aNumFmts);
++ }
++ }
++
++ // remove duplicates.
++ sort(aNumFmts.begin(), aNumFmts.end());
++ aNumFmts.erase(unique(aNumFmts.begin(), aNumFmts.end()), aNumFmts.end());
++ rNumFmts.swap(aNumFmts);
++}
++
++bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
++{
++ DocItem* pDoc = getDocItem(nFileId);
++ if (!pDoc)
++ return false;
++
++ String aUpperName = ScGlobal::pCharClass->upper(rTabName);
++ vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end();
++ vector<TableName>::const_iterator itr = ::std::find_if(
++ itrBeg, itrEnd, TabNameSearchPredicate(aUpperName));
++
++ return itr != itrEnd;
++}
++
++size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const
++{
++ DocItem* pDoc = getDocItem(nFileId);
++ return pDoc ? pDoc->maTables.size() : 0;
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++ DocItem* pDoc = getDocItem(nFileId);
++ if (!pDoc || nTabIndex >= pDoc->maTables.size())
++ return TableTypeRef();
++
++ return pDoc->maTables[nTabIndex];
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefCache::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
+{
+ DocItem* pDoc = getDocItem(nFileId);
+ if (!pDoc)
@@ -9004,18 +10011,23 @@
+ size_t nIndex;
+ String aTabNameUpper = ScGlobal::pCharClass->upper(rTabName);
+ if (lcl_getTableDataIndex(rDoc.maTableNameIndex, aTabNameUpper, nIndex))
++ {
+ // specified table found.
++ if( pnIndex ) *pnIndex = nIndex;
+ return rDoc.maTables[nIndex];
++ }
+
+ if (!bCreateNew)
+ return TableTypeRef();
+
+ // Specified table doesn't exist yet. Create one.
++ nIndex = rDoc.maTables.size();
++ if( pnIndex ) *pnIndex = nIndex;
+ TableTypeRef pTab(new Table);
+ rDoc.maTables.push_back(pTab);
+ rDoc.maTableNames.push_back(TableName(aTabNameUpper, rTabName));
+ rDoc.maTableNameIndex.insert(
-+ TableNameIndexMap::value_type(aTabNameUpper, rDoc.maTables.size()-1));
++ TableNameIndexMap::value_type(aTabNameUpper, nIndex));
+ return pTab;
+}
+
@@ -9109,41 +10121,50 @@
+
+static ScToken* lcl_convertToToken(ScBaseCell* pCell)
+{
-+ if (!pCell)
-+ return NULL;
++ if (!pCell || pCell->HasEmptyData())
++ {
++ bool bInherited = (pCell && pCell->GetCellType() == CELLTYPE_FORMULA);
++ return new ScEmptyCellToken( bInherited, false);
++ }
+
+ switch (pCell->GetCellType())
+ {
++ case CELLTYPE_EDIT:
++ {
++ String aStr;
++ static_cast<ScEditCell*>(pCell)->GetString(aStr);
++ return new ScStringToken(aStr);
++ }
++ break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
+ static_cast<ScStringCell*>(pCell)->GetString(aStr);
-+ ScStringToken aToken(aStr);
-+ return aToken.Clone();
++ return new ScStringToken(aStr);
+ }
+ break;
+ case CELLTYPE_VALUE:
+ {
+ double fVal = static_cast<ScValueCell*>(pCell)->GetValue();
-+ ScDoubleToken aToken(fVal);
-+ return aToken.Clone();
++ return new ScDoubleToken(fVal);
+ }
+ break;
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
-+ if (pFCell->IsValue())
++ USHORT nError = pFCell->GetErrCode();
++ if (nError)
++ return new ScErrorToken( nError);
++ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
-+ ScDoubleToken aToken(fVal);
-+ return aToken.Clone();
++ return new ScDoubleToken(fVal);
+ }
+ else
+ {
+ String aStr;
+ pFCell->GetString(aStr);
-+ ScStringToken aToken(aStr);
-+ return aToken.Clone();
++ return new ScStringToken(aStr);
+ }
+ }
+ break;
@@ -9154,7 +10175,7 @@
+ return NULL;
+}
+
-+static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
++static ScTokenArray* lcl_convertToTokenArray(ScDocument* pSrcDoc, const ScRange& rRange,
+ vector<ScExternalRefCache::SingleRangeData>& rCacheData)
+{
+ const ScAddress& s = rRange.aStart;
@@ -9164,9 +10185,17 @@
+ SCCOL nCol1 = s.Col(), nCol2 = e.Col();
+ SCROW nRow1 = s.Row(), nRow2 = e.Row();
+
++ if (nTab2 != nTab1)
++ // For now, we don't support multi-sheet ranges intentionally because
++ // we don't have a way to express them in a single token. In the
++ // future we can introduce a new stack variable type svMatrixList with
++ // a new token type that can store a 3D matrix value and convert a 3D
++ // range to it.
++ return NULL;
++
+ auto_ptr<ScTokenArray> pArray(new ScTokenArray);
+ bool bFirstTab = true;
-+ vector<ScExternalRefCache::SingleRangeData>::iterator
++ vector<ScExternalRefCache::SingleRangeData>::iterator
+ itrCache = rCacheData.begin(), itrCacheEnd = rCacheData.end();
+ for (SCTAB nTab = nTab1; nTab <= nTab2 && itrCache != itrCacheEnd; ++nTab, ++itrCache)
+ {
@@ -9181,10 +10210,19 @@
+ SCSIZE nC = nCol - nCol1, nR = nRow - nRow1;
+ ScBaseCell* pCell;
+ pSrcDoc->GetCell(nCol, nRow, nTab, pCell);
-+ if (pCell)
++ if (!pCell || pCell->HasEmptyData())
++ xMat->PutEmpty(nC, nR);
++ else
+ {
+ switch (pCell->GetCellType())
+ {
++ case CELLTYPE_EDIT:
++ {
++ String aStr;
++ static_cast<ScEditCell*>(pCell)->GetString(aStr);
++ xMat->PutString(aStr, nC, nR);
++ }
++ break;
+ case CELLTYPE_STRING:
+ {
+ String aStr;
@@ -9201,7 +10239,10 @@
+ case CELLTYPE_FORMULA:
+ {
+ ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell);
-+ if (pFCell->IsValue())
++ USHORT nError = pFCell->GetErrCode();
++ if (nError)
++ xMat->PutDouble( CreateDoubleError( nError), nC, nR);
++ else if (pFCell->IsValue())
+ {
+ double fVal = pFCell->GetValue();
+ xMat->PutDouble(fVal, nC, nR);
@@ -9218,10 +10259,6 @@
+ DBG_ERROR("attempted to convert an unknown cell type.");
+ }
+ }
-+ else
-+ {
-+ xMat->PutEmpty(nC, nR);
-+ }
+ }
+ }
+ if (!bFirstTab)
@@ -9250,9 +10287,269 @@
+ clear();
+}
+
-+ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew)
++String ScExternalRefManager::getCacheTableName(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++ return maRefCache.getTableName(nFileId, nTabIndex);
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, size_t nTabIndex) const
++{
++ return maRefCache.getCacheTable(nFileId, nTabIndex);
++}
++
++ScExternalRefCache::TableTypeRef ScExternalRefManager::getCacheTable(sal_uInt16 nFileId, const String& rTabName, bool bCreateNew, size_t* pnIndex)
++{
++ return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew, pnIndex);
++}
++
++// ============================================================================
++
++ScExternalRefManager::RefCells::TabItem::TabItem(SCTAB nIndex) :
++ mnIndex(nIndex)
++{
++}
++
++ScExternalRefManager::RefCells::TabItem::TabItem(const TabItem& r) :
++ mnIndex(r.mnIndex),
++ maCols(r.maCols)
++{
++}
++
++ScExternalRefManager::RefCells::RefCells()
++{
++}
++
++ScExternalRefManager::RefCells::~RefCells()
++{
++}
++
++list<ScExternalRefManager::RefCells::TabItemRef>::iterator ScExternalRefManager::RefCells::getTabPos(SCTAB nTab)
++{
++ list<TabItemRef>::iterator itr = maTables.begin(), itrEnd = maTables.end();
++ for (; itr != itrEnd; ++itr)
++ if ((*itr)->mnIndex >= nTab)
++ return itr;
++ // Not found. return the end position.
++ return itrEnd;
++}
++
++void ScExternalRefManager::RefCells::insertCell(const ScAddress& rAddr)
++{
++ SCTAB nTab = rAddr.Tab();
++ SCCOL nCol = rAddr.Col();
++ SCROW nRow = rAddr.Row();
++
++ // Search by table index.
++ list<TabItemRef>::iterator itrTab = getTabPos(nTab);
++ TabItemRef xTabRef;
++ if (itrTab == maTables.end())
++ {
++ // All previous tables come before the specificed table.
++ xTabRef.reset(new TabItem(nTab));
++ maTables.push_back(xTabRef);
++ }
++ else if ((*itrTab)->mnIndex > nTab)
++ {
++ // Insert at the current iterator position.
++ xTabRef.reset(new TabItem(nTab));
++ maTables.insert(itrTab, xTabRef);
++ }
++ else if ((*itrTab)->mnIndex == nTab)
++ {
++ // The table found.
++ xTabRef = *itrTab;
++ }
++ ColSet& rCols = xTabRef->maCols;
++
++ // Then by column index.
++ ColSet::iterator itrCol = rCols.find(nCol);
++ if (itrCol == rCols.end())
++ {
++ RowSet aRows;
++ pair<ColSet::iterator, bool> r = rCols.insert(ColSet::value_type(nCol, aRows));
++ if (!r.second)
++ // column insertion failed.
++ return;
++ itrCol = r.first;
++ }
++ RowSet& rRows = itrCol->second;
++
++ // Finally, insert the row index.
++ rRows.insert(nRow);
++}
++
++void ScExternalRefManager::RefCells::removeCell(const ScAddress& rAddr)
+{
-+ return maRefCache.getCacheTable(nFileId, rTabName, bCreateNew);
++ SCTAB nTab = rAddr.Tab();
++ SCCOL nCol = rAddr.Col();
++ SCROW nRow = rAddr.Row();
++
++ // Search by table index.
++ list<TabItemRef>::iterator itrTab = getTabPos(nTab);
++ if (itrTab == maTables.end() || (*itrTab)->mnIndex != nTab)
++ // No such table.
++ return;
++
++ ColSet& rCols = (*itrTab)->maCols;
++
++ // Then by column index.
++ ColSet::iterator itrCol = rCols.find(nCol);
++ if (itrCol == rCols.end())
++ // No such column
++ return;
++
++ RowSet& rRows = itrCol->second;
++ rRows.erase(nRow);
++}
++
++void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
++{
++ if (nOldTab == nNewTab)
++ // Nothing to do here.
++ return;
++
++ list<TabItemRef>::iterator itrOld = getTabPos(nOldTab);
++ if (itrOld == maTables.end() || (*itrOld)->mnIndex != nOldTab)
++ // No table to move or copy.
++ return;
++
++ list<TabItemRef>::iterator itrNew = getTabPos(nNewTab);
++ if (bCopy)
++ {
++ // Simply make a duplicate of the original table, insert it at the
++ // new tab position, and increment the table index for all tables
++ // that come after that inserted table.
++
++ TabItemRef xNewTab(new TabItem(*(*itrOld)));
++ xNewTab->mnIndex = nNewTab;
++ maTables.insert(itrNew, xNewTab);
++ list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end();
++ for (++itr; itr != itrEnd; ++itr)
++ (*itr)->mnIndex += 1;
++ }
++ else
++ {
++ if (itrOld == itrNew)
++ {
++ // No need to move the table. Just update the table index.
++ (*itrOld)->mnIndex = nNewTab;
++ return;
++ }
++
++ if (nOldTab < nNewTab)
++ {
++ // Iterate from the old tab position to the new tab position (not
++ // inclusive of the old tab itself), and decrement their tab
++ // index by one.
++ list<TabItemRef>::iterator itr = itrOld;
++ for (++itr; itr != itrNew; ++itr)
++ (*itr)->mnIndex -= 1;
++
++ // Insert a duplicate of the original table. This does not
++ // invalidate the iterators.
++ (*itrOld)->mnIndex = nNewTab - 1;
++ if (itrNew == maTables.end())
++ maTables.push_back(*itrOld);
++ else
++ maTables.insert(itrNew, *itrOld);
++
++ // Remove the original table.
++ maTables.erase(itrOld);
++ }
++ else
++ {
++ // nNewTab < nOldTab
++
++ // Iterate from the new tab position to the one before the old tab
++ // position, and increment their tab index by one.
++ list<TabItemRef>::iterator itr = itrNew;
++ for (++itr; itr != itrOld; ++itr)
++ (*itr)->mnIndex += 1;
++
++ (*itrOld)->mnIndex = nNewTab;
++ maTables.insert(itrNew, *itrOld);
++
++ // Remove the original table.
++ maTables.erase(itrOld);
++ }
++ }
++}
++
++void ScExternalRefManager::RefCells::insertTable(SCTAB nPos)
++{
++ TabItemRef xNewTab(new TabItem(nPos));
++ list<TabItemRef>::iterator itr = getTabPos(nPos);
++ if (itr == maTables.end())
++ maTables.push_back(xNewTab);
++ else
++ maTables.insert(itr, xNewTab);
++}
++
++void ScExternalRefManager::RefCells::removeTable(SCTAB nPos)
++{
++ list<TabItemRef>::iterator itr = getTabPos(nPos);
++ if (itr == maTables.end())
++ // nothing to remove.
++ return;
++
++ maTables.erase(itr);
++}
++
++void ScExternalRefManager::RefCells::refreshAllCells(ScExternalRefManager& rRefMgr)
++{
++ // Get ALL the cell positions for re-compilation.
++ for (list<TabItemRef>::iterator itrTab = maTables.begin(), itrTabEnd = maTables.end();
++ itrTab != itrTabEnd; ++itrTab)
++ {
++ SCTAB nTab = (*itrTab)->mnIndex;
++ ColSet& rCols = (*itrTab)->maCols;
++ for (ColSet::iterator itrCol = rCols.begin(), itrColEnd = rCols.end();
++ itrCol != itrColEnd; ++itrCol)
++ {
++ SCCOL nCol = itrCol->first;
++ RowSet& rRows = itrCol->second;
++ RowSet aNewRows;
++ for (RowSet::iterator itrRow = rRows.begin(), itrRowEnd = rRows.end();
++ itrRow != itrRowEnd; ++itrRow)
++ {
++ SCROW nRow = *itrRow;
++ ScAddress aCell(nCol, nRow, nTab);
++ if (rRefMgr.compileTokensByCell(aCell))
++ // This cell still contains an external refernce.
++ aNewRows.insert(nRow);
++ }
++ // Update the rows so that cells with no external references are
++ // no longer tracked.
++ rRows.swap(aNewRows);
++ }
++ }
++}
++
++// ----------------------------------------------------------------------------
++
++void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
++{
++ maRefCache.getAllTableNames(nFileId, rTabNames);
++}
++
++void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmts) const
++{
++ maRefCache.getAllNumberFormats(rNumFmts);
++}
++
++bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const
++{
++ return maRefCache.hasCacheTable(nFileId, rTabName);
++}
++
++size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const
++{
++ return maRefCache.getCacheTableCount(nFileId);
++}
++
++sal_uInt16 ScExternalRefManager::getExternalFileCount() const
++{
++ return static_cast< sal_uInt16 >( maSrcFiles.size() );
+}
+
+void ScExternalRefManager::storeRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScTokenArray& rArray)
@@ -9263,20 +10560,35 @@
+
+ScExternalRefCache::TokenRef ScExternalRefManager::getSingleRefToken(
+ sal_uInt16 nFileId, const String& rTabName, const ScAddress& rCell,
-+ const ScAddress* pCurPos, SCTAB* pTab)
++ const ScAddress* pCurPos, SCTAB* pTab, ScExternalRefCache::CellFormat* pFmt)
+{
+ if (pCurPos)
-+ insertReferencingCell(nFileId, *pCurPos);
++ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
+ if (pTab)
+ *pTab = -1;
+
++ if (pFmt)
++ pFmt->mbIsSet = false;
++
+ // Check if the given table name and the cell position is cached.
-+ ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(nFileId, rTabName, rCell.Row(), rCell.Col());
-+ if (pToken.get())
-+ {
++ sal_uInt32 nFmtIndex = 0;
++ ScExternalRefCache::TokenRef pToken = maRefCache.getCellData(
++ nFileId, rTabName, rCell.Row(), rCell.Col(), &nFmtIndex);
++ if (pToken)
++ {
++ if (pFmt)
++ {
++ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
++ if (nFmtType != NUMBERFORMAT_UNDEFINED)
++ {
++ pFmt->mbIsSet = true;
++ pFmt->mnIndex = nFmtIndex;
++ pFmt->mnType = nFmtType;
++ }
++ }
+ return pToken;
+ }
+
@@ -9299,23 +10611,36 @@
+ *pTab = nTab;
+
+ pSrcDoc->GetCell(rCell.Col(), rCell.Row(), nTab, pCell);
-+ TokenRef pTok(lcl_convertToToken(pCell));
++ ScExternalRefCache::TokenRef pTok(lcl_convertToToken(pCell));
++
++ pSrcDoc->GetNumberFormat(rCell.Col(), rCell.Row(), nTab, nFmtIndex);
++ nFmtIndex = getMappedNumberFormat(nFileId, nFmtIndex, pSrcDoc);
++ if (pFmt)
++ {
++ short nFmtType = mpDoc->GetFormatTable()->GetType(nFmtIndex);
++ if (nFmtType != NUMBERFORMAT_UNDEFINED)
++ {
++ pFmt->mbIsSet = true;
++ pFmt->mnIndex = nFmtIndex;
++ pFmt->mnType = nFmtType;
++ }
++ }
+
+ if (!pTok.get())
+ {
-+ // Cell in the source document is probably empty.
-+ pTok.reset(new ScEmptyCellToken(false, false));
++ // Generate an error for unresolvable cells.
++ pTok.reset( new ScErrorToken( errNoValue));
+ }
+
+ // Now, insert the token into cache table.
-+ maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok);
++ maRefCache.setCellData(nFileId, rTabName, rCell.Row(), rCell.Col(), pTok, nFmtIndex);
+ return pTok;
+}
+
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getDoubleRefTokens(sal_uInt16 nFileId, const String& rTabName, const ScRange& rRange, const ScAddress* pCurPos)
+{
+ if (pCurPos)
-+ insertReferencingCell(nFileId, *pCurPos);
++ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
@@ -9358,8 +10683,9 @@
+ ScExternalRefCache::TokenArrayRef pArray;
+ pArray.reset(lcl_convertToTokenArray(pSrcDoc, aRange, aCacheData));
+
-+ // Cache these values.
-+ maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
++ if (pArray)
++ // Cache these values.
++ maRefCache.setCellRangeData(nFileId, rRange, aCacheData, pArray);
+
+ return pArray;
+}
@@ -9367,7 +10693,7 @@
+ScExternalRefCache::TokenArrayRef ScExternalRefManager::getRangeNameTokens(sal_uInt16 nFileId, const String& rName, const ScAddress* pCurPos)
+{
+ if (pCurPos)
-+ insertReferencingCell(nFileId, *pCurPos);
++ insertRefCell(nFileId, *pCurPos);
+
+ maybeLinkExternalFile(nFileId);
+
@@ -9390,12 +10716,12 @@
+ if (!pRangeData)
+ return ScExternalRefCache::TokenArrayRef();
+
-+ // Parse all tokens in this external range data, and replace each absolute
++ // Parse all tokens in this external range data, and replace each absolute
+ // reference token with an external reference token, and cache them. Also
+ // register the source document with the link manager if it's a new
+ // source.
+
-+ TokenArrayRef pNew(new ScTokenArray);
++ ScExternalRefCache::TokenArrayRef pNew(new ScTokenArray);
+
+ ScTokenArray* pCode = pRangeData->GetCode();
+ for (ScToken* pToken = pCode->First(); pToken; pToken = pCode->Next())
@@ -9426,7 +10752,7 @@
+ default:
+ ; // nothing to do
+ }
-+
++
+ if (!bTokenAdded)
+ pNew->AddToken(*pToken);
+ }
@@ -9436,22 +10762,14 @@
+ return pNew;
+}
+
-+void ScExternalRefManager::refreshAllReferencingCells(sal_uInt16 nFileId)
++void ScExternalRefManager::refreshAllRefCells(sal_uInt16 nFileId)
+{
-+ RefCellMap::iterator itr = maRefCells.find(nFileId);
-+ if (itr == maRefCells.end())
++ RefCellMap::iterator itrFile = maRefCells.find(nFileId);
++ if (itrFile == maRefCells.end())
+ return;
+
-+ RefCellSet aNewSet;
-+ RefCellSet& rSet = itr->second;
-+ RefCellSet::const_iterator itrSet = rSet.begin(), itrSetEnd = rSet.end();
-+ for (; itrSet != itrSetEnd; ++itrSet)
-+ {
-+ if (compileTokensByCell(*itrSet))
-+ // Cell still contains an external name/ref token.
-+ aNewSet.insert(*itrSet);
-+ }
-+ rSet.swap(aNewSet);
++ RefCells& rRefCells = itrFile->second;
++ rRefCells.refreshAllCells(*this);
+
+ ScViewData* pViewData = ScDocShell::GetViewData();
+ if (!pViewData)
@@ -9467,22 +10785,28 @@
+ pVShell->PaintGrid();
+}
+
-+void ScExternalRefManager::insertReferencingCell(sal_uInt16 nFileId, const ScAddress& rCell)
++void ScExternalRefManager::insertRefCell(sal_uInt16 nFileId, const ScAddress& rCell)
+{
+ RefCellMap::iterator itr = maRefCells.find(nFileId);
-+ if (itr != maRefCells.end())
++ if (itr == maRefCells.end())
+ {
-+ itr->second.insert(rCell);
-+ return;
-+ }
++ RefCells aRefCells;
++ pair<RefCellMap::iterator, bool> r = maRefCells.insert(
++ RefCellMap::value_type(nFileId, aRefCells));
++ if (!r.second)
++ // insertion failed.
++ return;
+
-+ RefCellSet aSet;
-+ aSet.insert(rCell);
-+ maRefCells.insert(RefCellMap::value_type(nFileId, aSet));
++ itr = r.first;
++ }
++ itr->second.insertCell(rCell);
+}
+
+ScDocument* ScExternalRefManager::getSrcDocument(sal_uInt16 nFileId)
+{
++ if (!mpDoc->IsExecuteLinkEnabled())
++ return NULL;
++
+ DocShellMap::iterator itrEnd = maDocShells.end();
+ DocShellMap::iterator itr = maDocShells.find(nFileId);
+
@@ -9543,7 +10867,7 @@
+ String aFile = pFileData->maFileName;
+ if (!isFileLoadable(aFile))
+ {
-+ // The original file path is not loadable. Try the relative path.
++ // 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.
+
@@ -9697,30 +11021,8 @@
+ rFile = ScGlobal::GetAbsDocName(rFile, pDocShell);
+}
+
-+namespace {
-+
-+class FindSrcFileByName : public ::std::unary_function<ScExternalRefManager::SrcFileData, bool>
-+{
-+public:
-+ FindSrcFileByName(const String& rMatchName) :
-+ mrMatchName(rMatchName)
-+ {
-+ }
-+
-+ bool operator()(const ScExternalRefManager::SrcFileData& rSrcData) const
-+ {
-+ return rSrcData.maFileName.Equals(mrMatchName);
-+ }
-+
-+private:
-+ const String& mrMatchName;
-+};
-+
-+}
+sal_uInt16 ScExternalRefManager::getExternalFileId(const String& rFile)
+{
-+ using namespace std;
-+
+ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
+ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
+ if (itr != itrEnd)
@@ -9743,6 +11045,18 @@
+ return &maSrcFiles[nFileId].maFileName;
+}
+
++bool ScExternalRefManager::hasExternalFile(sal_uInt16 nFileId) const
++{
++ return nFileId < maSrcFiles.size();
++}
++
++bool ScExternalRefManager::hasExternalFile(const String& rFile) const
++{
++ vector<SrcFileData>::const_iterator itrBeg = maSrcFiles.begin(), itrEnd = maSrcFiles.end();
++ vector<SrcFileData>::const_iterator itr = find_if(itrBeg, itrEnd, FindSrcFileByName(rFile));
++ return itr != itrEnd;
++}
++
+const ScExternalRefManager::SrcFileData* ScExternalRefManager::getExternalFileData(sal_uInt16 nFileId) const
+{
+ if (nFileId >= maSrcFiles.size())
@@ -9761,16 +11075,6 @@
+ return maRefCache.getRealRangeName(nFileId, rRangeName);
+}
+
-+void ScExternalRefManager::getAllCachedTableNames(sal_uInt16 nFileId, vector<String>& rTabNames) const
-+{
-+ maRefCache.getAllTableNames(nFileId, rTabNames);
-+}
-+
-+sal_uInt16 ScExternalRefManager::getCachedFileCount() const
-+{
-+ return static_cast<sal_uInt16>(maSrcFiles.size());
-+}
-+
+template<typename MapContainer>
+static void lcl_removeByFileId(sal_uInt16 nFileId, MapContainer& rMap)
+{
@@ -9784,7 +11088,7 @@
+ removeSrcDocument(nFileId, false);
+
+ // Update all cells containing names from this source document.
-+ refreshAllReferencingCells(nFileId);
++ refreshAllRefCells(nFileId);
+}
+
+void ScExternalRefManager::switchSrcFile(sal_uInt16 nFileId, const String& rNewFile)
@@ -9852,6 +11156,34 @@
+ }
+}
+
++void ScExternalRefManager::updateRefCell(const ScAddress& rOldPos, const ScAddress& rNewPos, bool bCopy)
++{
++ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++ {
++ if (!bCopy)
++ itr->second.removeCell(rOldPos);
++ itr->second.insertCell(rNewPos);
++ }
++}
++
++void ScExternalRefManager::updateRefMoveTable(SCTAB nOldTab, SCTAB nNewTab, bool bCopy)
++{
++ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++ itr->second.moveTable(nOldTab, nNewTab, bCopy);
++}
++
++void ScExternalRefManager::updateRefInsertTable(SCTAB nPos)
++{
++ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++ itr->second.insertTable(nPos);
++}
++
++void ScExternalRefManager::updateRefDeleteTable(SCTAB nPos)
++{
++ for (RefCellMap::iterator itr = maRefCells.begin(), itrEnd = maRefCells.end(); itr != itrEnd; ++itr)
++ itr->second.removeTable(nPos);
++}
++
+void ScExternalRefManager::purgeStaleSrcDocument(sal_Int32 nTimeOut)
+{
+ DocShellMap aNewDocShells;
@@ -9859,7 +11191,7 @@
+ for (; itr != itrEnd; ++itr)
+ {
+ // in 100th of a second.
-+ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
++ sal_Int32 nSinceLastAccess = (Time() - itr->second.maLastAccess).GetTime();
+ if (nSinceLastAccess < nTimeOut)
+ aNewDocShells.insert(*itr);
+ }
@@ -9869,6 +11201,33 @@
+ maSrcDocTimer.Stop();
+}
+
++sal_uInt32 ScExternalRefManager::getMappedNumberFormat(sal_uInt16 nFileId, sal_uInt32 nNumFmt, ScDocument* pSrcDoc)
++{
++ NumFmtMap::iterator itr = maNumFormatMap.find(nFileId);
++ if (itr == maNumFormatMap.end())
++ {
++ // Number formatter map is not initialized for this external document.
++ pair<NumFmtMap::iterator, bool> r = maNumFormatMap.insert(
++ NumFmtMap::value_type(nFileId, SvNumberFormatterMergeMap()));
++
++ if (!r.second)
++ // insertion failed.
++ return nNumFmt;
++
++ itr = r.first;
++ mpDoc->GetFormatTable()->MergeFormatter( *pSrcDoc->GetFormatTable());
++ SvNumberFormatterMergeMap aMap = mpDoc->GetFormatTable()->ConvertMergeTableToMap();
++ itr->second.swap(aMap);
++ }
++ const SvNumberFormatterMergeMap& rMap = itr->second;
++ SvNumberFormatterMergeMap::const_iterator itrNumFmt = rMap.find(nNumFmt);
++ if (itrNumFmt != rMap.end())
++ // mapped value found.
++ return itrNumFmt->second;
++
++ return nNumFmt;
++}
++
+IMPL_LINK(ScExternalRefManager, TimeOutHdl, AutoTimer*, pTimer)
+{
+ if (pTimer == &maSrcDocTimer)
@@ -9913,11 +11272,62 @@
$(SLO)$/tablink.obj \
$(SLO)$/arealink.obj \
$(SLO)$/dbdocfun.obj \
+diff --git sc/source/ui/unoobj/cellsuno.cxx sc/source/ui/unoobj/cellsuno.cxx
+index 7e1ec2d..7c0e769 100644
+--- sc/source/ui/unoobj/cellsuno.cxx
++++ sc/source/ui/unoobj/cellsuno.cxx
+@@ -2408,7 +2408,7 @@ void ScCellRangesBase::GetOnePropertyValue( const SfxItemPropertyMap* pMap,
+ case ATTR_VALUE_FORMAT:
+ {
+ ScDocument* pDoc = pDocShell->GetDocument();
+-
++
+ ULONG nOldFormat = ((const SfxUInt32Item&)
+ pDataSet->Get( ATTR_VALUE_FORMAT )).GetValue();
+ LanguageType eOldLang = ((const SvxLanguageItem&)
+@@ -5176,7 +5176,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens() thr
+ {
+ ScTokenArray* pTokenArray = pFCell1->GetCode();
+ if ( pTokenArray )
+- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
+ }
+ }
+ }
+@@ -5198,8 +5198,9 @@ void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::Formula
+ throw uno::RuntimeException();
+ }
+
++ ScDocument* pDoc = pDocSh->GetDocument();
+ ScTokenArray aTokenArray;
+- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
++ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
+
+ // Actually GRAM_PODF_A1 is a don't-care here because of the token
+ // array being set, it fits with other API compatibility grammars
+@@ -6597,7 +6598,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens() throw(uno::Ru
+ {
+ ScTokenArray* pTokenArray = static_cast<ScFormulaCell*>(pCell)->GetCode();
+ if ( pTokenArray )
+- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray );
+ }
+ }
+ return aSequence;
+@@ -6611,7 +6612,7 @@ void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rT
+ {
+ ScDocument* pDoc = pDocSh->GetDocument();
+ ScTokenArray aTokenArray;
+- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
++ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens );
+
+ ScDocFunc aFunc( *pDocSh );
+ ScBaseCell* pNewCell = new ScFormulaCell( pDoc, aCellPos, &aTokenArray );
diff --git sc/source/ui/unoobj/docuno.cxx sc/source/ui/unoobj/docuno.cxx
-index 5a8c983..6a2fabf 100644
+index 875259a..b2e6ee7 100644
--- sc/source/ui/unoobj/docuno.cxx
+++ sc/source/ui/unoobj/docuno.cxx
-@@ -123,6 +123,7 @@ const SfxItemPropertyMap* lcl_GetDocOptPropertyMap()
+@@ -124,6 +124,7 @@ const SfxItemPropertyMap* lcl_GetDocOptPropertyMap()
{MAP_CHAR_LEN(SC_UNO_COLLABELRNG), 0, &getCppuType((uno::Reference<sheet::XLabelRanges>*)0), 0, 0},
{MAP_CHAR_LEN(SC_UNO_DDELINKS), 0, &getCppuType((uno::Reference<container::XNameAccess>*)0), 0, 0},
{MAP_CHAR_LEN(SC_UNO_DEFTABSTOP), 0, &getCppuType((sal_Int16*)0), 0, 0},
@@ -9925,7 +11335,7 @@
{MAP_CHAR_LEN(SC_UNO_FORBIDDEN), 0, &getCppuType((uno::Reference<i18n::XForbiddenCharacters>*)0), beans::PropertyAttribute::READONLY, 0},
{MAP_CHAR_LEN(SC_UNO_HASDRAWPAGES), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0},
{MAP_CHAR_LEN(SC_UNO_IGNORECASE), 0, &getBooleanCppuType(), 0, 0},
-@@ -1537,6 +1538,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
+@@ -1538,6 +1539,10 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa
{
aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell ));
}
@@ -9936,17 +11346,56 @@
else if ( aString.EqualsAscii( SC_UNO_SHEETLINKS ) )
{
aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell ));
+diff --git sc/source/ui/unoobj/fmtuno.cxx sc/source/ui/unoobj/fmtuno.cxx
+index eb9f55b..c41ebe5 100644
+--- sc/source/ui/unoobj/fmtuno.cxx
++++ sc/source/ui/unoobj/fmtuno.cxx
+@@ -197,14 +197,14 @@ void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat,
+ if ( aData.maTokens1.getLength() )
+ {
+ ScTokenArray aTokenArray;
+- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens1) )
++ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens1) )
+ aCoreEntry.SetFormula1(aTokenArray);
+ }
+
+ if ( aData.maTokens2.getLength() )
+ {
+ ScTokenArray aTokenArray;
+- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aData.maTokens2) )
++ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens2) )
+ aCoreEntry.SetFormula2(aTokenArray);
+ }
+ rFormat.AddEntry( aCoreEntry );
+@@ -660,14 +660,14 @@ ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc,
+ if ( aTokens1.getLength() )
+ {
+ ScTokenArray aTokenArray;
+- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens1) )
++ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens1) )
+ pRet->SetFormula1(aTokenArray);
+ }
+
+ if ( aTokens2.getLength() )
+ {
+ ScTokenArray aTokenArray;
+- if ( ScTokenConversion::ConvertToTokenArray(aTokenArray, aTokens2) )
++ if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens2) )
+ pRet->SetFormula2(aTokenArray);
+ }
+
diff --git sc/source/ui/unoobj/linkuno.cxx sc/source/ui/unoobj/linkuno.cxx
-index 52a5a62..7fb3e01 100644
+index 52a5a62..7131ed4 100644
--- sc/source/ui/unoobj/linkuno.cxx
+++ sc/source/ui/unoobj/linkuno.cxx
-@@ -48,8 +48,20 @@
+@@ -48,8 +48,21 @@
#include "hints.hxx"
#include "unonames.hxx"
#include "rangeseq.hxx"
+#include "token.hxx"
+
+#include <vector>
++#include <climits>
using namespace com::sun::star;
+using ::com::sun::star::uno::Any;
@@ -9961,15 +11410,16 @@
//------------------------------------------------------------------------
-@@ -1480,4 +1492,229 @@ uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
+@@ -1480,4 +1493,327 @@ uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink(
return xLink;
}
-//------------------------------------------------------------------------
+// ============================================================================
+
-+ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable) :
-+ mpTable(pTable)
++ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) :
++ mpTable(pTable),
++ mnIndex(nIndex)
+{
+}
+
@@ -9977,7 +11427,7 @@
+{
+}
+
-+void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nRow, sal_Int32 nCol, const Any& rValue)
++void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue)
+ throw (IllegalArgumentException, RuntimeException)
+{
+ ScUnoGuard aGuard;
@@ -9995,17 +11445,17 @@
+ // unidentified value type.
+ return;
+
-+ mpTable->setCell(static_cast<SCROW>(nRow), static_cast<SCCOL>(nCol), pToken);
++ mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken);
+}
+
-+Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nRow, sal_Int32 nCol)
++Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow)
+ throw (IllegalArgumentException, RuntimeException)
+{
+ ScUnoGuard aGuard;
+ if (nRow < 0 || nCol < 0)
+ throw IllegalArgumentException();
+
-+ ScToken* pToken = mpTable->getCell(nRow, nCol).get();
++ ScToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get();
+ if (!pToken)
+ throw IllegalArgumentException();
+
@@ -10061,6 +11511,12 @@
+ return aColsSeq;
+}
+
++sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex()
++ throw (RuntimeException)
++{
++ return static_cast< sal_Int32 >( mnIndex );
++}
++
+// ============================================================================
+
+ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) :
@@ -10077,11 +11533,98 @@
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true);
-+ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable));
++ size_t nIndex = 0;
++ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex);
++ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
+ return aSheetCache;
+}
+
++Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName)
++ throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
++{
++ ScUnoGuard aGuard;
++ size_t nIndex = 0;
++ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex);
++ if (!pTable)
++ throw container::NoSuchElementException();
++
++ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
++
++ Any aAny;
++ aAny <<= aSheetCache;
++ return aAny;
++}
++
++Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames()
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ vector<String> aTabNames;
++ mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames);
++ size_t n = aTabNames.size();
++ Sequence<OUString> aSeq(n);
++ for (size_t i = 0; i < n; ++i)
++ aSeq[i] = aTabNames[i];
++ return aSeq;
++}
++
++sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName)
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ return static_cast<sal_Bool>(mpRefMgr->hasCacheTable(mnFileId, aName));
++}
++
++sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount()
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ return static_cast<sal_Int32>(mpRefMgr->getCacheTableCount(mnFileId));
++}
++
++Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nIndex)
++ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
++{
++ ScUnoGuard aGuard;
++ size_t nTabCount = mpRefMgr->getCacheTableCount(mnFileId);
++ if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(nTabCount))
++ throw lang::IndexOutOfBoundsException();
++
++ ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, static_cast<size_t>(nIndex));
++ if (!pTable)
++ throw lang::IndexOutOfBoundsException();
++
++ Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex));
++
++ Any aAny;
++ aAny <<= aSheetCache;
++ return aAny;
++}
++
++Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration()
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ Reference< container::XEnumeration > aRef(
++ new ScIndexEnumeration(this, OUString::createFromAscii(
++ "com.sun.star.sheet.ExternalDocLink")));
++ return aRef;
++}
++
++uno::Type SAL_CALL ScExternalDocLinkObj::getElementType()
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0));
++}
++
++sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements()
++ throw (RuntimeException)
++{
++ ScUnoGuard aGuard;
++ return static_cast<sal_Bool>(mpRefMgr->getCacheTableCount(mnFileId) > 0);
++}
++
+sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex()
+ throw (RuntimeException)
+{
@@ -10107,68 +11650,72 @@
+ ScUnoGuard aGuard;
+ sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName);
+ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
-+ maDocLinks.insert( DocLinkMap::value_type(aDocName, aDocLink) );
-+ maDocNames.push_back(aDocName);
+ return aDocLink;
+}
+
-+Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName)
++Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName)
+ throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ DocLinkMap::const_iterator itr = maDocLinks.find(aName);
-+ if (itr == maDocLinks.end())
++ if (!mpRefMgr->hasExternalFile(aName))
+ throw container::NoSuchElementException();
+
++ sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName);
++ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
++
+ Any aAny;
-+ aAny <<= itr->second;
++ aAny <<= aDocLink;
+ return aAny;
+}
+
-+Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
++Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ size_t n = maDocNames.size();
++ sal_uInt16 n = mpRefMgr->getExternalFileCount();
+ Sequence<OUString> aSeq(n);
-+ for (size_t i = 0; i < n; ++i)
-+ aSeq[i] = maDocNames[i];
++ for (sal_uInt16 i = 0; i < n; ++i)
++ {
++ const String* pName = mpRefMgr->getExternalFileName(i);
++ aSeq[i] = pName ? *pName : EMPTY_STRING;
++ }
++
+ return aSeq;
+}
+
-+sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
++sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName)
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ return static_cast<sal_Bool>(maDocLinks.count(aName) > 0);
++ return mpRefMgr->hasExternalFile(aName);
+}
+
-+sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
++sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ return static_cast<sal_Int32>(maDocLinks.size());
++ return mpRefMgr->getExternalFileCount();
+}
+
-+Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
++Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex)
+ throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(maDocNames.size()))
++ if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min())
+ throw lang::IndexOutOfBoundsException();
+
-+ const OUString& rDocName = maDocNames[nIndex];
-+ DocLinkMap::const_iterator itr = maDocLinks.find(rDocName);
-+ if (itr == maDocLinks.end())
-+ // This should never happen!
++ sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex);
++
++ if (!mpRefMgr->hasExternalFile(nFileId))
+ throw lang::IndexOutOfBoundsException();
+
++ Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId));
+ Any aAny;
-+ aAny <<= itr->second;
++ aAny <<= aDocLink;
+ return aAny;
+}
+
-+Reference< container::XEnumeration >SAL_CALL ScExternalDocLinksObj::createEnumeration()
++Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
@@ -10178,25 +11725,87 @@
+ return aRef;
+}
+
-+uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
++uno::Type SAL_CALL ScExternalDocLinksObj::getElementType()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
+ return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0));
+}
+
-+sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
++sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements()
+ throw (RuntimeException)
+{
+ ScUnoGuard aGuard;
-+ return static_cast<sal_Bool>(!maDocLinks.empty());
++ return mpRefMgr->getExternalFileCount() > 0;
+}
+
+diff --git sc/source/ui/unoobj/nameuno.cxx sc/source/ui/unoobj/nameuno.cxx
+index 1335b36..b303be0 100644
+--- sc/source/ui/unoobj/nameuno.cxx
++++ sc/source/ui/unoobj/nameuno.cxx
+@@ -313,11 +313,11 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
+ ScUnoGuard aGuard;
+ uno::Sequence<sheet::FormulaToken> aSequence;
+ ScRangeData* pData = GetRangeData_Impl();
+- if (pData)
++ if (pData && pDocShell)
+ {
+ ScTokenArray* pTokenArray = pData->GetCode();
+ if ( pTokenArray )
+- (void)ScTokenConversion::ConvertToTokenSequence( aSequence, *pTokenArray );
++ (void)ScTokenConversion::ConvertToTokenSequence( *pDocShell->GetDocument(), aSequence, *pTokenArray );
+ }
+ return aSequence;
+ }
+@@ -325,10 +325,13 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(u
+ void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException)
+ {
+ ScUnoGuard aGuard;
+- ScTokenArray aTokenArray;
+- (void)ScTokenConversion::ConvertToTokenArray( aTokenArray, rTokens );
+- // GRAM_PODF_A1 for API compatibility.
+- Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
++ if( pDocShell )
++ {
++ ScTokenArray aTokenArray;
++ (void)ScTokenConversion::ConvertToTokenArray( *pDocShell->GetDocument(), aTokenArray, rTokens );
++ // GRAM_PODF_A1 for API compatibility.
++ Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, ScGrammar::GRAM_PODF_A1 );
++ }
+ }
+
+
diff --git sc/source/ui/unoobj/tokenuno.cxx sc/source/ui/unoobj/tokenuno.cxx
-index f16b1c5..f968d7b 100644
+index f16b1c5..1435cde 100644
--- sc/source/ui/unoobj/tokenuno.cxx
+++ sc/source/ui/unoobj/tokenuno.cxx
-@@ -123,6 +123,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
+@@ -31,15 +31,16 @@
+ // MARKER(update_precomp.py): autogen include statement, do not remove
+ #include "precompiled_sc.hxx"
+
++#include "tokenuno.hxx"
+
+ #include <com/sun/star/sheet/ComplexReference.hpp>
++#include <com/sun/star/sheet/ExternalReference.hpp>
+ #include <com/sun/star/sheet/ReferenceFlags.hpp>
+ #include <com/sun/star/sheet/AddressConvention.hpp>
+ #include <com/sun/star/table/CellAddress.hpp>
+
+ #include <svtools/itemprop.hxx>
+
+-#include "tokenuno.hxx"
+ #include "miscuno.hxx"
+ #include "convuno.hxx"
+ #include "unonames.hxx"
+@@ -48,6 +49,7 @@
+ #include "tokenarray.hxx"
+ #include "docsh.hxx"
+ #include "rangeseq.hxx"
++#include "externalrefmgr.hxx"
+
+ using namespace com::sun::star;
+
+@@ -123,6 +125,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const
eConv = aConvMap[mnConv];
rCompiler.SetRefConvention( eConv );
@@ -10205,7 +11814,25 @@
}
uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula )
-@@ -220,6 +222,11 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
+@@ -138,7 +142,7 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co
+ SetCompilerFlags( aCompiler );
+
+ ScTokenArray* pCode = aCompiler.CompileString( aFormula );
+- (void)ScTokenConversion::ConvertToTokenSequence( aRet, *pCode );
++ (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode );
+ delete pCode;
+ }
+
+@@ -155,7 +159,7 @@ rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<she
+ {
+ ScDocument* pDoc = mpDocShell->GetDocument();
+ ScTokenArray aCode;
+- (void)ScTokenConversion::ConvertToTokenArray( aCode, aTokens );
++ (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens );
+ ScCompiler aCompiler( pDoc, maRefPos, aCode, pDoc->GetGrammar() );
+ SetCompilerFlags( aCompiler );
+
+@@ -220,6 +224,11 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue(
else
throw lang::IllegalArgumentException();
}
@@ -10217,7 +11844,7 @@
else
throw beans::UnknownPropertyException();
}
-@@ -253,6 +260,10 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
+@@ -253,6 +262,10 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr
{
aRet <<= maOpCodeMapping;
}
@@ -10228,19 +11855,204 @@
else
throw beans::UnknownPropertyException();
return aRet;
-@@ -473,7 +484,12 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
+@@ -262,6 +275,27 @@ SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj )
+
+ //------------------------------------------------------------------------
+
++void lcl_ExternalRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
++{
++ rRef.InitFlags();
++
++ rRef.nCol = static_cast<SCsCOL>(rAPI.Column);
++ rRef.nRow = static_cast<SCsROW>(rAPI.Row);
++ rRef.nTab = 0;
++ rRef.nRelCol = static_cast<SCsCOL>(rAPI.RelativeColumn);
++ rRef.nRelRow = static_cast<SCsROW>(rAPI.RelativeRow);
++ rRef.nRelTab = 0;
++
++ rRef.SetColRel( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_RELATIVE ) != 0 );
++ rRef.SetRowRel( ( rAPI.Flags & sheet::ReferenceFlags::ROW_RELATIVE ) != 0 );
++ rRef.SetTabRel( false ); // sheet index must be absolute for external refs
++ rRef.SetColDeleted( ( rAPI.Flags & sheet::ReferenceFlags::COLUMN_DELETED ) != 0 );
++ rRef.SetRowDeleted( ( rAPI.Flags & sheet::ReferenceFlags::ROW_DELETED ) != 0 );
++ rRef.SetTabDeleted( false ); // sheet must not be deleted for external refs
++ rRef.SetFlag3D( ( rAPI.Flags & sheet::ReferenceFlags::SHEET_3D ) != 0 );
++ rRef.SetRelName( false );
++}
++
+ void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAPI )
+ {
+ rRef.InitFlags();
+@@ -283,6 +317,25 @@ void lcl_SingleRefToCalc( SingleRefData& rRef, const sheet::SingleReference& rAP
+ rRef.SetRelName( ( rAPI.Flags & sheet::ReferenceFlags::RELATIVE_NAME ) != 0 );
+ }
+
++void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
++{
++ rAPI.Column = rRef.nCol;
++ rAPI.Row = rRef.nRow;
++ rAPI.Sheet = 0;
++ rAPI.RelativeColumn = rRef.nRelCol;
++ rAPI.RelativeRow = rRef.nRelRow;
++ rAPI.RelativeSheet = 0;
++
++ sal_Int32 nFlags = 0;
++ if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE;
++ if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE;
++ if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED;
++ if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED;
++ if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D;
++ if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME;
++ rAPI.Flags = nFlags;
++}
++
+ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef )
+ {
+ rAPI.Column = rRef.nCol;
+@@ -305,8 +358,8 @@ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const SingleRefData& rRef
+ }
+
+ // static
+-bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+- const uno::Sequence<sheet::FormulaToken>& rSequence )
++bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc,
++ ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence )
+ {
+ bool bError = false;
+ sal_Int32 nCount = rSequence.getLength();
+@@ -384,6 +437,59 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+ else
+ bError = true;
+ }
++ else if ( aType.equals( cppu::UnoType<sheet::ExternalReference>::get() ) )
++ {
++ sheet::ExternalReference aApiExtRef;
++ if( (eOpCode == ocPush) && (rAPI.Data >>= aApiExtRef) && (0 <= aApiExtRef.Index) && (aApiExtRef.Index <= SAL_MAX_UINT16) )
++ {
++ sal_uInt16 nFileId = static_cast< sal_uInt16 >( aApiExtRef.Index );
++ sheet::SingleReference aApiSRef;
++ sheet::ComplexReference aApiCRef;
++ ::rtl::OUString aName;
++ if( aApiExtRef.Reference >>= aApiSRef )
++ {
++ // try to resolve cache index to sheet name
++ size_t nCacheId = static_cast< size_t >( aApiSRef.Sheet );
++ String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
++ if( aTabName.Len() > 0 )
++ {
++ SingleRefData aSingleRef;
++ // convert column/row settings, set sheet index to absolute
++ lcl_ExternalRefToCalc( aSingleRef, aApiSRef );
++ rTokenArray.AddExternalSingleReference( nFileId, aTabName, aSingleRef );
++ }
++ else
++ bError = true;
++ }
++ else if( aApiExtRef.Reference >>= aApiCRef )
++ {
++ // try to resolve cache index to sheet name. TODO: second cache index is dropped
++ size_t nCacheId = static_cast< size_t >( aApiCRef.Reference1.Sheet );
++ String aTabName = rDoc.GetExternalRefManager()->getCacheTableName( nFileId, nCacheId );
++ if( aTabName.Len() > 0 )
++ {
++ ComplRefData aComplRef;
++ // convert column/row settings, set sheet index to absolute
++ lcl_ExternalRefToCalc( aComplRef.Ref1, aApiCRef.Reference1 );
++ lcl_ExternalRefToCalc( aComplRef.Ref2, aApiCRef.Reference2 );
++ rTokenArray.AddExternalDoubleReference( nFileId, aTabName, aComplRef );
++ }
++ else
++ bError = true;
++ }
++ else if( aApiExtRef.Reference >>= aName )
++ {
++ if( aName.getLength() > 0 )
++ rTokenArray.AddExternalName( nFileId, aName );
++ else
++ bError = true;
++ }
++ else
++ bError = true;
++ }
++ else
++ bError = true;
++ }
+ else
+ bError = true; // unknown struct
+ }
+@@ -414,8 +520,8 @@ bool ScTokenConversion::ConvertToTokenArray( ScTokenArray& rTokenArray,
+ }
+
+ // static
+-bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToken>& rSequence,
+- const ScTokenArray& rTokenArray )
++bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc,
++ uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray )
+ {
+ bool bError = false;
+
+@@ -430,7 +536,7 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
+ sheet::FormulaToken& rAPI = rSequence[nPos];
+
+ OpCode eOpCode = rToken.GetOpCode();
+- rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
++ // eOpCode may be changed in the following switch/case
+ switch ( rToken.GetType() )
+ {
+ case svByte:
+@@ -473,9 +579,52 @@ bool ScTokenConversion::ConvertToTokenSequence( uno::Sequence<sheet::FormulaToke
if (!ScRangeToSequence::FillMixedArray( rAPI.Data, rToken.GetMatrix(), true))
rAPI.Data.clear();
break;
+ case svExternalSingleRef:
++ {
++ sheet::SingleReference aSingleRef;
++ lcl_ExternalRefToApi( aSingleRef, rToken.GetSingleRef() );
++ size_t nCacheId;
++ rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
++ aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId );
++ sheet::ExternalReference aExtRef;
++ aExtRef.Index = rToken.GetIndex();
++ aExtRef.Reference <<= aSingleRef;
++ rAPI.Data <<= aExtRef;
++ eOpCode = ocPush;
++ }
++ break;
+ case svExternalDoubleRef:
++ {
++ sheet::ComplexReference aComplRef;
++ lcl_ExternalRefToApi( aComplRef.Reference1, rToken.GetSingleRef() );
++ lcl_ExternalRefToApi( aComplRef.Reference2, rToken.GetSingleRef2() );
++ size_t nCacheId;
++ rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId );
++ aComplRef.Reference1.Sheet = aComplRef.Reference2.Sheet = static_cast< sal_Int32 >( nCacheId );
++ sheet::ExternalReference aExtRef;
++ aExtRef.Index = rToken.GetIndex();
++ aExtRef.Reference <<= aComplRef;
++ rAPI.Data <<= aExtRef;
++ eOpCode = ocPush;
++ }
++ break;
+ case svExternalName:
-+ // FIXME: svExternal... are to be transported via API.
++ {
++ sheet::ExternalReference aExtRef;
++ aExtRef.Index = rToken.GetIndex();
++ aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() );
++ rAPI.Data <<= aExtRef;
++ eOpCode = ocPush;
++ }
++ break;
default:
+ DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType());
++ case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray*
++ case svJump: // occurs with ocIf, ocChose
++ case svMissing: // occurs with ocMissing
rAPI.Data.clear(); // no data
}
++ rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment
}
+ }
+ else
diff --git sc/source/ui/view/tabvwsh4.cxx sc/source/ui/view/tabvwsh4.cxx
index 436f0eb..2bf1f26 100644
--- sc/source/ui/view/tabvwsh4.cxx
Added: branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff
==============================================================================
--- (empty file)
+++ branches/ooo-build-3-0-1/patches/dev300/calc-external-defined-names-svtools.diff Thu Jan 15 02:44:24 2009
@@ -0,0 +1,61 @@
+diff --git svtools/inc/svtools/zforlist.hxx svtools/inc/svtools/zforlist.hxx
+index 20d4752..1e4f122 100644
+--- svtools/inc/svtools/zforlist.hxx
++++ svtools/inc/svtools/zforlist.hxx
+@@ -45,6 +45,8 @@
+ #include <tools/link.hxx>
+ #include <svtools/nfkeytab.hxx>
+
++#include <map>
++
+ class Date;
+ class SvStream;
+ class Color;
+@@ -224,6 +226,8 @@ typedef Table SvNumberFormatTable;
+ typedef Table SvNumberFormatterIndexTable;
+ #endif
+
++typedef ::std::map< sal_uInt32, sal_uInt32 > SvNumberFormatterMergeMap;
++
+
+ /** Language/country dependent currency entries
+ */
+@@ -599,6 +603,11 @@ public:
+ /// Return the new format index for an old format index, if a merge table exists
+ inline sal_uInt32 GetMergeFmtIndex( sal_uInt32 nOldFmt ) const;
+
++ /** Convert the ugly old tools' Table type bloated with new'ed sal_uInt32
++ entries merge table to ::std::map with old index key and new index key.
++ @ATTENTION! Also clears the old table using ClearMergeTable() */
++ SvNumberFormatterMergeMap ConvertMergeTableToMap();
++
+ /// Return the last used position ever of a language/country combination
+ USHORT GetLastInsertKey(sal_uInt32 CLOffset);
+
+diff --git svtools/source/numbers/zforlist.cxx svtools/source/numbers/zforlist.cxx
+index b093e0d..adc7e70 100644
+--- svtools/source/numbers/zforlist.cxx
++++ svtools/source/numbers/zforlist.cxx
+@@ -2914,6 +2914,22 @@ SvNumberFormatterIndexTable* SvNumberFormatter::MergeFormatter(SvNumberFormatter
+ }
+
+
++SvNumberFormatterMergeMap SvNumberFormatter::ConvertMergeTableToMap()
++{
++ if (!HasMergeFmtTbl())
++ return SvNumberFormatterMergeMap();
++
++ SvNumberFormatterMergeMap aMap;
++ for (sal_uInt32* pIndex = pMergeTable->First(); pIndex; pIndex = pMergeTable->Next())
++ {
++ sal_uInt32 nOldKey = pMergeTable->GetCurKey();
++ aMap.insert( SvNumberFormatterMergeMap::value_type( nOldKey, *pIndex));
++ }
++ ClearMergeTable();
++ return aMap;
++}
++
++
+ sal_uInt32 SvNumberFormatter::GetFormatForLanguageIfBuiltIn( sal_uInt32 nFormat,
+ LanguageType eLnge )
+ {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]