Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include "xelink.hxx"
21 :
22 : #include <algorithm>
23 : #include <unotools/collatorwrapper.hxx>
24 : #include <svl/zforlist.hxx>
25 : #include "document.hxx"
26 : #include "formulacell.hxx"
27 : #include "scextopt.hxx"
28 : #include "externalrefmgr.hxx"
29 : #include "tokenarray.hxx"
30 :
31 : #include <vector>
32 : #include <memory>
33 :
34 : using ::std::auto_ptr;
35 : using ::std::find_if;
36 : using ::std::vector;
37 : using ::com::sun::star::uno::Any;
38 :
39 :
40 : // *** Helper classes ***
41 :
42 :
43 : // External names =============================================================
44 :
45 : /** This is a base class for any external name (i.e. add-in names or DDE links).
46 : @descr Derived classes implement creation and export of the external names. */
47 : class XclExpExtNameBase : public XclExpRecord, protected XclExpRoot
48 : {
49 : public:
50 : /** @param nFlags The flags to export. */
51 : explicit XclExpExtNameBase( const XclExpRoot& rRoot,
52 : const OUString& rName, sal_uInt16 nFlags = 0 );
53 : virtual ~XclExpExtNameBase();
54 :
55 : /** Returns the name string of the external name. */
56 0 : inline const OUString& GetName() const { return maName; }
57 :
58 : private:
59 : /** Writes the start of the record that is equal in all EXTERNNAME records and calls WriteAddData(). */
60 : virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
61 : /** Called to write additional data following the common record contents.
62 : @descr Derived classes should overwrite this function to write their data. */
63 : virtual void WriteAddData( XclExpStream& rStrm );
64 :
65 : private:
66 : OUString maName; /// Calc name (title) of the external name.
67 : XclExpStringRef mxName; /// Excel name (title) of the external name.
68 : sal_uInt16 mnFlags; /// Flags for record export.
69 : };
70 :
71 : /** Represents an EXTERNNAME record for an add-in function name. */
72 0 : class XclExpExtNameAddIn : public XclExpExtNameBase
73 : {
74 : public:
75 : explicit XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName );
76 :
77 : private:
78 : /** Writes additional record contents. */
79 : virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
80 : };
81 :
82 : /** Represents an EXTERNNAME record for a DDE link. */
83 0 : class XclExpExtNameDde : public XclExpExtNameBase
84 : {
85 : public:
86 : explicit XclExpExtNameDde( const XclExpRoot& rRoot, const OUString& rName,
87 : sal_uInt16 nFlags, const ScMatrix* pResults = 0 );
88 :
89 : private:
90 : /** Writes additional record contents. */
91 : virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
92 :
93 : private:
94 : typedef boost::shared_ptr< XclExpCachedMatrix > XclExpCachedMatRef;
95 : XclExpCachedMatRef mxMatrix; /// Cached results of the DDE link.
96 : };
97 :
98 : class XclExpSupbook;
99 :
100 0 : class XclExpExtName : public XclExpExtNameBase
101 : {
102 : public:
103 : explicit XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook, const OUString& rName,
104 : const ScExternalRefCache::TokenArrayRef pArray );
105 :
106 : private:
107 : /** Writes additional record contents. */
108 : virtual void WriteAddData( XclExpStream& rStrm ) SAL_OVERRIDE;
109 :
110 : private:
111 : const XclExpSupbook& mrSupbook;
112 : auto_ptr<ScTokenArray> mpArray;
113 : };
114 :
115 : // List of external names =====================================================
116 :
117 : /** List of all external names of a sheet. */
118 0 : class XclExpExtNameBuffer : public XclExpRecordBase, protected XclExpRoot
119 : {
120 : public:
121 : explicit XclExpExtNameBuffer( const XclExpRoot& rRoot );
122 :
123 : /** Inserts an add-in function name
124 : @return The 1-based (Excel-like) list index of the name. */
125 : sal_uInt16 InsertAddIn( const OUString& rName );
126 : /** InsertEuroTool */
127 : sal_uInt16 InsertEuroTool( const OUString& rName );
128 : /** Inserts a DDE link.
129 : @return The 1-based (Excel-like) list index of the DDE link. */
130 : sal_uInt16 InsertDde( const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
131 :
132 : sal_uInt16 InsertExtName( const XclExpSupbook& rSupbook, const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray );
133 :
134 : /** Writes the EXTERNNAME record list. */
135 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
136 :
137 : private:
138 : typedef XclExpRecordList< XclExpExtNameBase > XclExpExtNameList;
139 : typedef XclExpExtNameList::RecordRefType XclExpExtNameRef;
140 :
141 : private:
142 : /** Returns the 1-based (Excel-like) list index of the external name or 0, if not found. */
143 : sal_uInt16 GetIndex( const OUString& rName ) const;
144 : /** Appends the passed newly crested external name.
145 : @return The 1-based (Excel-like) list index of the appended name. */
146 : sal_uInt16 AppendNew( XclExpExtNameBase* pExtName );
147 :
148 : private:
149 : XclExpExtNameList maNameList; /// The list with all EXTERNNAME records.
150 : };
151 :
152 : // Cached external cells ======================================================
153 :
154 : /** Stores the contents of a consecutive row of external cells (record CRN). */
155 0 : class XclExpCrn : public XclExpRecord
156 : {
157 : public:
158 : explicit XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue );
159 :
160 : /** Returns true, if the passed value could be appended to this record. */
161 : bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
162 :
163 : private:
164 : virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
165 :
166 : void WriteBool( XclExpStream& rStrm, bool bValue );
167 : void WriteDouble( XclExpStream& rStrm, double fValue );
168 : void WriteString( XclExpStream& rStrm, const OUString& rValue );
169 : void WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode );
170 : void WriteEmpty( XclExpStream& rStrm );
171 :
172 : private:
173 : typedef ::std::vector< Any > CachedValues;
174 :
175 : CachedValues maValues; /// All cached values.
176 : SCCOL mnScCol; /// Column index of the first external cell.
177 : SCROW mnScRow; /// Row index of the external cells.
178 : };
179 :
180 : /** Represents the record XCT which is the header record of a CRN record list.
181 : */
182 0 : class XclExpXct : public XclExpRecordBase, protected XclExpRoot
183 : {
184 : public:
185 : explicit XclExpXct( const XclExpRoot& rRoot,
186 : const OUString& rTabName, sal_uInt16 nSBTab,
187 : ScExternalRefCache::TableTypeRef xCacheTable );
188 :
189 : /** Returns the external sheet name. */
190 0 : inline const XclExpString& GetTabName() const { return maTabName; }
191 :
192 : /** Stores all cells in the given range in the CRN list. */
193 : void StoreCellRange( const ScRange& rRange );
194 :
195 : void StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken );
196 : void StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken );
197 :
198 : /** Writes the XCT and all CRN records. */
199 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
200 :
201 : private:
202 : ScExternalRefCache::TableTypeRef mxCacheTable;
203 : ScMarkData maUsedCells; /// Contains addresses of all stored cells.
204 : ScRange maBoundRange; /// Bounding box of maUsedCells.
205 : XclExpString maTabName; /// Sheet name of the external sheet.
206 : sal_uInt16 mnSBTab; /// Referred sheet index in SUPBOOK record.
207 : };
208 :
209 : // External documents (EXTERNSHEET/SUPBOOK), base class =======================
210 :
211 : /** Base class for records representing external sheets/documents.
212 :
213 : In BIFF5/BIFF7, this record is the EXTERNSHEET record containing one sheet
214 : of the own or an external document. In BIFF8, this record is the SUPBOOK
215 : record representing the entire own or external document with all referenced
216 : sheets.
217 : */
218 0 : class XclExpExternSheetBase : public XclExpRecord, protected XclExpRoot
219 : {
220 : public:
221 : explicit XclExpExternSheetBase( const XclExpRoot& rRoot,
222 : sal_uInt16 nRecId, sal_uInt32 nRecSize = 0 );
223 :
224 : protected:
225 : /** Creates and returns the list of EXTERNNAME records. */
226 : XclExpExtNameBuffer& GetExtNameBuffer();
227 : /** Creates and returns the list of EXTERNNAME records. */
228 : void WriteExtNameBuffer( XclExpStream& rStrm );
229 :
230 : private:
231 : typedef boost::shared_ptr< XclExpExtNameBuffer > XclExpExtNameBfrRef;
232 : XclExpExtNameBfrRef mxExtNameBfr; /// List of EXTERNNAME records.
233 : };
234 :
235 : // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
236 :
237 : /** Represents an EXTERNSHEET record containing the URL and sheet name of a sheet.
238 : @descr This class is used up to BIFF7 only, writing a BIFF8 EXTERNSHEET
239 : record is implemented directly in the link manager. */
240 0 : class XclExpExternSheet : public XclExpExternSheetBase
241 : {
242 : public:
243 : /** Creates an EXTERNSHEET record containing a special code (i.e. own document or sheet). */
244 : explicit XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode );
245 : /** Creates an EXTERNSHEET record referring to an internal sheet. */
246 : explicit XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName );
247 :
248 : /** Finds or inserts an EXTERNNAME record for add-ins.
249 : @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
250 : sal_uInt16 InsertAddIn( const OUString& rName );
251 :
252 : /** Writes the EXTERNSHEET and all EXTERNNAME, XCT and CRN records. */
253 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
254 :
255 : private:
256 : /** Initializes the record data with the passed encoded URL. */
257 : void Init( const OUString& rEncUrl );
258 : /** Writes the contents of the EXTERNSHEET record. */
259 : virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
260 :
261 : private:
262 : XclExpString maTabName; /// The name of the sheet.
263 : };
264 :
265 : // External documents (SUPBOOK, BIFF8) ========================================
266 :
267 : /** The SUPBOOK record contains data for an external document (URL, sheet names, external values). */
268 0 : class XclExpSupbook : public XclExpExternSheetBase
269 : {
270 : public:
271 : /** Creates a SUPBOOK record for internal references. */
272 : explicit XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount );
273 : /** Creates a SUPBOOK record for add-in functions. */
274 : explicit XclExpSupbook( const XclExpRoot& rRoot );
275 : /** EUROTOOL SUPBOOK */
276 : explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType );
277 : /** Creates a SUPBOOK record for an external document. */
278 : explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl );
279 : /** Creates a SUPBOOK record for a DDE link. */
280 : explicit XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic );
281 :
282 : /** Returns true, if this SUPBOOK contains the passed URL of an external document. */
283 : bool IsUrlLink( const OUString& rUrl ) const;
284 : /** Returns true, if this SUPBOOK contains the passed DDE link. */
285 : bool IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const;
286 : /** Fills the passed reference log entry with the URL and sheet names. */
287 : void FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
288 : sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const;
289 :
290 : /** Stores all cells in the given range in the CRN list of the specified SUPBOOK sheet. */
291 : void StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab );
292 :
293 : void StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const ::formula::FormulaToken& rToken );
294 : void StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const ::formula::FormulaToken& rToken );
295 :
296 : sal_uInt16 GetTabIndex( const OUString& rTabName ) const;
297 : sal_uInt16 GetTabCount() const;
298 :
299 : /** Inserts a new sheet name into the SUPBOOK and returns the SUPBOOK internal sheet index. */
300 : sal_uInt16 InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable );
301 : /** Finds or inserts an EXTERNNAME record for add-ins.
302 : @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
303 : sal_uInt16 InsertAddIn( const OUString& rName );
304 : /** InsertEuroTool */
305 : sal_uInt16 InsertEuroTool( const OUString& rName );
306 : /** Finds or inserts an EXTERNNAME record for DDE links.
307 : @return The 1-based EXTERNNAME record index; or 0, if the record list is full. */
308 : sal_uInt16 InsertDde( const OUString& rItem );
309 :
310 : sal_uInt16 InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray );
311 :
312 : /** Writes the SUPBOOK and all EXTERNNAME, XCT and CRN records. */
313 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
314 :
315 : private:
316 : /** Returns the sheet name inside of this SUPBOOK. */
317 : const XclExpString* GetTabName( sal_uInt16 nSBTab ) const;
318 :
319 : /** Writes the SUPBOOK record contents. */
320 : virtual void WriteBody( XclExpStream& rStrm ) SAL_OVERRIDE;
321 :
322 : private:
323 : typedef XclExpRecordList< XclExpXct > XclExpXctList;
324 : typedef XclExpXctList::RecordRefType XclExpXctRef;
325 :
326 : XclExpXctList maXctList; /// List of XCT records (which contain CRN records).
327 : OUString maUrl; /// URL of the external document or application name for DDE.
328 : OUString maDdeTopic; /// Topic of an DDE link.
329 : XclExpString maUrlEncoded; /// Document name encoded for Excel.
330 : XclSupbookType meType; /// Type of this SUPBOOK record.
331 : sal_uInt16 mnXclTabCount; /// Number of internal sheets.
332 : };
333 :
334 : // All SUPBOOKS in a document =================================================
335 :
336 : /** This struct contains a sheet index range for 3D references.
337 : @descr This reference consists of an index to a SUPBOOK record and indexes
338 : to SUPBOOK sheet names. */
339 : struct XclExpXti
340 : {
341 : sal_uInt16 mnSupbook; /// Index to SUPBOOK record.
342 : sal_uInt16 mnFirstSBTab; /// Index to the first sheet of the range in the SUPBOOK.
343 : sal_uInt16 mnLastSBTab; /// Index to the last sheet of the range in the SUPBOOK.
344 :
345 0 : inline explicit XclExpXti() : mnSupbook( 0 ), mnFirstSBTab( 0 ), mnLastSBTab( 0 ) {}
346 0 : inline explicit XclExpXti( sal_uInt16 nSupbook, sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) :
347 0 : mnSupbook( nSupbook ), mnFirstSBTab( nFirstSBTab ), mnLastSBTab( nLastSBTab ) {}
348 :
349 : /** Writes this XTI structure (inside of the EXTERNSHEET record). */
350 0 : inline void Save( XclExpStream& rStrm ) const
351 0 : { rStrm << mnSupbook << mnFirstSBTab << mnLastSBTab; }
352 : };
353 :
354 0 : inline bool operator==( const XclExpXti& rLeft, const XclExpXti& rRight )
355 : {
356 : return
357 0 : (rLeft.mnSupbook == rRight.mnSupbook) &&
358 0 : (rLeft.mnFirstSBTab == rRight.mnFirstSBTab) &&
359 0 : (rLeft.mnLastSBTab == rRight.mnLastSBTab);
360 : }
361 :
362 : /** Contains a list of all SUPBOOK records and index arrays of external sheets. */
363 0 : class XclExpSupbookBuffer : public XclExpRecordBase, protected XclExpRoot
364 : {
365 : public:
366 : explicit XclExpSupbookBuffer( const XclExpRoot& rRoot );
367 :
368 : /** Finds SUPBOOK index and SUPBOOK sheet range from given Excel sheet range.
369 : @return An XTI structure containing SUPBOOK and sheet indexes. */
370 : XclExpXti GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
371 : XclExpRefLogEntry* pRefLogEntry = 0 ) const;
372 :
373 : /** Stores all cells in the given range in a CRN record list. */
374 : void StoreCellRange( const ScRange& rRange );
375 :
376 : void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell );
377 : void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange );
378 :
379 : /** Finds or inserts an EXTERNNAME record for an add-in function name.
380 : @param rnSupbook Returns the index of the SUPBOOK record which contains the add-in function name.
381 : @param rnExtName Returns the 1-based EXTERNNAME record index. */
382 : bool InsertAddIn(
383 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
384 : const OUString& rName );
385 : /** InsertEuroTool */
386 : bool InsertEuroTool(
387 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
388 : const OUString& rName );
389 : /** Finds or inserts an EXTERNNAME record for DDE links.
390 : @param rnSupbook Returns the index of the SUPBOOK record which contains the DDE link.
391 : @param rnExtName Returns the 1-based EXTERNNAME record index. */
392 : bool InsertDde(
393 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
394 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem );
395 :
396 : bool InsertExtName(
397 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
398 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray );
399 :
400 : XclExpXti GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
401 : XclExpRefLogEntry* pRefLogEntry = NULL );
402 :
403 : /** Writes all SUPBOOK records with their sub records. */
404 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
405 :
406 : struct XclExpSBIndex
407 : {
408 : sal_uInt16 mnSupbook; /// SUPBOOK index for an Excel sheet.
409 : sal_uInt16 mnSBTab; /// Sheet name index in SUPBOOK for an Excel sheet.
410 0 : inline void Set( sal_uInt16 nSupbook, sal_uInt16 nSBTab )
411 0 : { mnSupbook = nSupbook; mnSBTab = nSBTab; }
412 : };
413 : typedef ::std::vector< XclExpSBIndex > XclExpSBIndexVec;
414 :
415 : private:
416 : typedef XclExpRecordList< XclExpSupbook > XclExpSupbookList;
417 : typedef XclExpSupbookList::RecordRefType XclExpSupbookRef;
418 :
419 : private:
420 : /** Searches for the SUPBOOK record containing the passed document URL.
421 : @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
422 : @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
423 : @return True, if the SUPBOOK record exists (out-parameters are valid). */
424 : bool GetSupbookUrl( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
425 : const OUString& rUrl ) const;
426 : /** Searches for the SUPBOOK record containing the passed DDE link.
427 : @param rxSupbook (out-param) Returns a reference to the SUPBOOK record, or 0.
428 : @param rnIndex (out-param) Returns the list index, if the SUPBOOK exists.
429 : @return True, if the SUPBOOK record exists (out-parameters are valid). */
430 : bool GetSupbookDde( XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex,
431 : const OUString& rApplic, const OUString& rTopic ) const;
432 :
433 : /** Appends a new SUPBOOK to the list.
434 : @return The list index of the SUPBOOK record. */
435 : sal_uInt16 Append( XclExpSupbookRef xSupbook );
436 :
437 : private:
438 : XclExpSupbookList maSupbookList; /// List of all SUPBOOK records.
439 : XclExpSBIndexVec maSBIndexVec; /// SUPBOOK and sheet name index for each Excel sheet.
440 : sal_uInt16 mnOwnDocSB; /// Index to SUPBOOK for own document.
441 : sal_uInt16 mnAddInSB; /// Index to add-in SUPBOOK.
442 : };
443 :
444 : // Export link manager ========================================================
445 :
446 : /** Abstract base class for implementation classes of the link manager. */
447 0 : class XclExpLinkManagerImpl : protected XclExpRoot
448 : {
449 : public:
450 : /** Derived classes search for an EXTSHEET structure for the given Calc sheet range. */
451 : virtual void FindExtSheet( sal_uInt16& rnExtSheet,
452 : sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
453 : SCTAB nFirstScTab, SCTAB nLastScTab,
454 : XclExpRefLogEntry* pRefLogEntry ) = 0;
455 : /** Derived classes search for a special EXTERNSHEET index for the own document. */
456 : virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) = 0;
457 :
458 : virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
459 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
460 : XclExpRefLogEntry* pRefLogEntry ) = 0;
461 :
462 : /** Derived classes store all cells in the given range in a CRN record list. */
463 : virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) = 0;
464 :
465 : virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) = 0;
466 : virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) = 0;
467 :
468 : /** Derived classes find or insert an EXTERNNAME record for an add-in function name. */
469 : virtual bool InsertAddIn(
470 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
471 : const OUString& rName ) = 0;
472 : /** InsertEuroTool */
473 : virtual bool InsertEuroTool(
474 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
475 : const OUString& rName ) = 0;
476 :
477 : /** Derived classes find or insert an EXTERNNAME record for DDE links. */
478 : virtual bool InsertDde(
479 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
480 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) = 0;
481 :
482 : virtual bool InsertExtName(
483 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
484 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray ) = 0;
485 :
486 : /** Derived classes write the entire link table to the passed stream. */
487 : virtual void Save( XclExpStream& rStrm ) = 0;
488 :
489 : protected:
490 : explicit XclExpLinkManagerImpl( const XclExpRoot& rRoot );
491 : };
492 :
493 : /** Implementation of the link manager for BIFF5/BIFF7. */
494 0 : class XclExpLinkManagerImpl5 : public XclExpLinkManagerImpl
495 : {
496 : public:
497 : explicit XclExpLinkManagerImpl5( const XclExpRoot& rRoot );
498 :
499 : virtual void FindExtSheet( sal_uInt16& rnExtSheet,
500 : sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
501 : SCTAB nFirstScTab, SCTAB nLastScTab,
502 : XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
503 : virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
504 :
505 : virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
506 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
507 : XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
508 :
509 : virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
510 :
511 : virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
512 : virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
513 :
514 : virtual bool InsertAddIn(
515 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
516 : const OUString& rName ) SAL_OVERRIDE;
517 :
518 : /** InsertEuroTool */
519 : virtual bool InsertEuroTool(
520 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
521 : const OUString& rName ) SAL_OVERRIDE;
522 :
523 : virtual bool InsertDde(
524 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
525 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
526 :
527 : virtual bool InsertExtName(
528 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
529 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray ) SAL_OVERRIDE;
530 :
531 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
532 :
533 : private:
534 : typedef XclExpRecordList< XclExpExternSheet > XclExpExtSheetList;
535 : typedef XclExpExtSheetList::RecordRefType XclExpExtSheetRef;
536 : typedef ::std::map< SCTAB, sal_uInt16 > XclExpIntTabMap;
537 : typedef ::std::map< sal_Unicode, sal_uInt16 > XclExpCodeMap;
538 :
539 : private:
540 : /** Returns the number of EXTERNSHEET records. */
541 : sal_uInt16 GetExtSheetCount() const;
542 :
543 : /** Appends an internal EXTERNSHEET record and returns the one-based index. */
544 : sal_uInt16 AppendInternal( XclExpExtSheetRef xExtSheet );
545 : /** Creates all EXTERNSHEET records for internal sheets on first call. */
546 : void CreateInternal();
547 :
548 : /** Returns the specified internal EXTERNSHEET record. */
549 : XclExpExtSheetRef GetInternal( sal_uInt16 nExtSheet );
550 : /** Returns the EXTERNSHEET index of an internal Calc sheet, or a deleted reference. */
551 : XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab );
552 : /** Finds or creates the EXTERNSHEET index of an internal special EXTERNSHEET. */
553 : XclExpExtSheetRef FindInternal( sal_uInt16& rnExtSheet, sal_Unicode cCode );
554 :
555 : private:
556 : XclExpExtSheetList maExtSheetList; /// List with EXTERNSHEET records.
557 : XclExpIntTabMap maIntTabMap; /// Maps internal Calc sheets to EXTERNSHEET records.
558 : XclExpCodeMap maCodeMap; /// Maps special external codes to EXTERNSHEET records.
559 : };
560 :
561 : /** Implementation of the link manager for BIFF8. */
562 0 : class XclExpLinkManagerImpl8 : public XclExpLinkManagerImpl
563 : {
564 : public:
565 : explicit XclExpLinkManagerImpl8( const XclExpRoot& rRoot );
566 :
567 : virtual void FindExtSheet( sal_uInt16& rnExtSheet,
568 : sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
569 : SCTAB nFirstScTab, SCTAB nLastScTab,
570 : XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
571 : virtual sal_uInt16 FindExtSheet( sal_Unicode cCode ) SAL_OVERRIDE;
572 :
573 : virtual void FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
574 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
575 : XclExpRefLogEntry* pRefLogEntry ) SAL_OVERRIDE;
576 :
577 : virtual void StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos ) SAL_OVERRIDE;
578 :
579 : virtual void StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos ) SAL_OVERRIDE;
580 : virtual void StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange ) SAL_OVERRIDE;
581 :
582 : virtual bool InsertAddIn(
583 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
584 : const OUString& rName ) SAL_OVERRIDE;
585 : /** InsertEuroTool */
586 : virtual bool InsertEuroTool(
587 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
588 : const OUString& rName ) SAL_OVERRIDE;
589 :
590 : virtual bool InsertDde(
591 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
592 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem ) SAL_OVERRIDE;
593 :
594 : virtual bool InsertExtName(
595 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rUrl,
596 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray ) SAL_OVERRIDE;
597 :
598 : virtual void Save( XclExpStream& rStrm ) SAL_OVERRIDE;
599 :
600 : private:
601 : /** Searches for or inserts a new XTI structure.
602 : @return The 0-based list index of the XTI structure. */
603 : sal_uInt16 InsertXti( const XclExpXti& rXti );
604 :
605 : private:
606 : typedef ::std::vector< XclExpXti > XclExpXtiVec;
607 :
608 : XclExpSupbookBuffer maSBBuffer; /// List of all SUPBOOK records.
609 : XclExpXtiVec maXtiVec; /// List of XTI structures for the EXTERNSHEET record.
610 : };
611 :
612 :
613 : // *** Implementation ***
614 :
615 :
616 : // Excel sheet indexes ========================================================
617 :
618 : const sal_uInt8 EXC_TABBUF_IGNORE = 0x01; /// Sheet will be ignored completely.
619 : const sal_uInt8 EXC_TABBUF_EXTERN = 0x02; /// Sheet is linked externally.
620 : const sal_uInt8 EXC_TABBUF_SKIPMASK = 0x0F; /// Sheet will be skipped, if any flag is set.
621 : const sal_uInt8 EXC_TABBUF_VISIBLE = 0x10; /// Sheet is visible.
622 : const sal_uInt8 EXC_TABBUF_SELECTED = 0x20; /// Sheet is selected.
623 : const sal_uInt8 EXC_TABBUF_MIRRORED = 0x40; /// Sheet is mirrored (right-to-left).
624 :
625 0 : XclExpTabInfo::XclExpTabInfo( const XclExpRoot& rRoot ) :
626 : XclExpRoot( rRoot ),
627 : mnScCnt( 0 ),
628 : mnXclCnt( 0 ),
629 : mnXclExtCnt( 0 ),
630 : mnXclSelCnt( 0 ),
631 : mnDisplXclTab( 0 ),
632 0 : mnFirstVisXclTab( 0 )
633 : {
634 0 : ScDocument& rDoc = GetDoc();
635 0 : ScExtDocOptions& rDocOpt = GetExtDocOptions();
636 :
637 0 : mnScCnt = rDoc.GetTableCount();
638 :
639 : SCTAB nScTab;
640 0 : SCTAB nFirstVisScTab = SCTAB_INVALID; // first visible sheet
641 0 : SCTAB nFirstExpScTab = SCTAB_INVALID; // first exported sheet
642 :
643 : // --- initialize the flags in the index buffer ---
644 :
645 0 : maTabInfoVec.resize( mnScCnt );
646 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
647 : {
648 : // ignored sheets (skipped by export, with invalid Excel sheet index)
649 0 : if( rDoc.IsScenario( nScTab ) )
650 : {
651 0 : SetFlag( nScTab, EXC_TABBUF_IGNORE );
652 : }
653 :
654 : // external sheets (skipped, but with valid Excel sheet index for ref's)
655 0 : else if( rDoc.GetLinkMode( nScTab ) == SC_LINK_VALUE )
656 : {
657 0 : SetFlag( nScTab, EXC_TABBUF_EXTERN );
658 : }
659 :
660 : // exported sheets
661 : else
662 : {
663 : // sheet name
664 0 : rDoc.GetName( nScTab, maTabInfoVec[ nScTab ].maScName );
665 :
666 : // remember first exported sheet
667 0 : if( nFirstExpScTab == SCTAB_INVALID )
668 0 : nFirstExpScTab = nScTab;
669 : // remember first visible exported sheet
670 0 : if( (nFirstVisScTab == SCTAB_INVALID) && rDoc.IsVisible( nScTab ) )
671 0 : nFirstVisScTab = nScTab;
672 :
673 : // sheet visible (only exported sheets)
674 0 : SetFlag( nScTab, EXC_TABBUF_VISIBLE, rDoc.IsVisible( nScTab ) );
675 :
676 : // sheet selected (only exported sheets)
677 0 : if( const ScExtTabSettings* pTabSett = rDocOpt.GetTabSettings( nScTab ) )
678 0 : SetFlag( nScTab, EXC_TABBUF_SELECTED, pTabSett->mbSelected );
679 :
680 : // sheet mirrored (only exported sheets)
681 0 : SetFlag( nScTab, EXC_TABBUF_MIRRORED, rDoc.IsLayoutRTL( nScTab ) );
682 : }
683 : }
684 :
685 : // --- visible/selected sheets ---
686 :
687 0 : SCTAB nDisplScTab = rDocOpt.GetDocSettings().mnDisplTab;
688 :
689 : // find first visible exported sheet
690 0 : if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
691 : {
692 : // no exportable visible sheet -> use first exportable sheet
693 0 : nFirstVisScTab = nFirstExpScTab;
694 0 : if( (nFirstVisScTab == SCTAB_INVALID) || !IsExportTab( nFirstVisScTab ) )
695 : {
696 : // no exportable sheet at all -> use active sheet and export it
697 0 : nFirstVisScTab = nDisplScTab;
698 0 : SetFlag( nFirstVisScTab, EXC_TABBUF_SKIPMASK, false ); // clear skip flags
699 : }
700 0 : SetFlag( nFirstVisScTab, EXC_TABBUF_VISIBLE ); // must be visible, even if originally hidden
701 : }
702 :
703 : // find currently displayed sheet
704 0 : if( !IsExportTab( nDisplScTab ) ) // selected sheet not exported (i.e. scenario) -> use first visible
705 0 : nDisplScTab = nFirstVisScTab;
706 0 : SetFlag( nDisplScTab, EXC_TABBUF_VISIBLE | EXC_TABBUF_SELECTED );
707 :
708 : // number of selected sheets
709 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
710 0 : if( IsSelectedTab( nScTab ) )
711 0 : ++mnXclSelCnt;
712 :
713 : // --- calculate resulting Excel sheet indexes ---
714 :
715 0 : CalcXclIndexes();
716 0 : mnFirstVisXclTab = GetXclTab( nFirstVisScTab );
717 0 : mnDisplXclTab = GetXclTab( nDisplScTab );
718 :
719 : // --- sorted vectors for index lookup ---
720 :
721 0 : CalcSortedIndexes();
722 0 : }
723 :
724 0 : bool XclExpTabInfo::IsExportTab( SCTAB nScTab ) const
725 : {
726 : /* Check sheet index before to avoid assertion in GetFlag(). */
727 0 : return (nScTab < mnScCnt) && !GetFlag( nScTab, EXC_TABBUF_SKIPMASK );
728 : }
729 :
730 0 : bool XclExpTabInfo::IsExternalTab( SCTAB nScTab ) const
731 : {
732 : /* Check sheet index before to avoid assertion (called from formula
733 : compiler also for deleted references). */
734 0 : return (nScTab < mnScCnt) && GetFlag( nScTab, EXC_TABBUF_EXTERN );
735 : }
736 :
737 0 : bool XclExpTabInfo::IsVisibleTab( SCTAB nScTab ) const
738 : {
739 0 : return GetFlag( nScTab, EXC_TABBUF_VISIBLE );
740 : }
741 :
742 0 : bool XclExpTabInfo::IsSelectedTab( SCTAB nScTab ) const
743 : {
744 0 : return GetFlag( nScTab, EXC_TABBUF_SELECTED );
745 : }
746 :
747 0 : bool XclExpTabInfo::IsDisplayedTab( SCTAB nScTab ) const
748 : {
749 : OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::IsActiveTab - sheet out of range" );
750 0 : return GetXclTab( nScTab ) == mnDisplXclTab;
751 : }
752 :
753 0 : bool XclExpTabInfo::IsMirroredTab( SCTAB nScTab ) const
754 : {
755 0 : return GetFlag( nScTab, EXC_TABBUF_MIRRORED );
756 : }
757 :
758 0 : OUString XclExpTabInfo::GetScTabName( SCTAB nScTab ) const
759 : {
760 : OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::IsActiveTab - sheet out of range" );
761 0 : return (nScTab < mnScCnt) ? maTabInfoVec[ nScTab ].maScName : OUString();
762 : }
763 :
764 0 : sal_uInt16 XclExpTabInfo::GetXclTab( SCTAB nScTab ) const
765 : {
766 0 : return (nScTab < mnScCnt) ? maTabInfoVec[ nScTab ].mnXclTab : EXC_TAB_DELETED;
767 : }
768 :
769 0 : SCTAB XclExpTabInfo::GetRealScTab( SCTAB nSortedScTab ) const
770 : {
771 : OSL_ENSURE( nSortedScTab < mnScCnt, "XclExpTabInfo::GetRealScTab - sheet out of range" );
772 0 : return (nSortedScTab < mnScCnt) ? maFromSortedVec[ nSortedScTab ] : SCTAB_INVALID;
773 : }
774 :
775 0 : bool XclExpTabInfo::GetFlag( SCTAB nScTab, sal_uInt8 nFlags ) const
776 : {
777 : OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::GetFlag - sheet out of range" );
778 0 : return (nScTab < mnScCnt) && ::get_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags );
779 : }
780 :
781 0 : void XclExpTabInfo::SetFlag( SCTAB nScTab, sal_uInt8 nFlags, bool bSet )
782 : {
783 : OSL_ENSURE( nScTab < mnScCnt, "XclExpTabInfo::SetFlag - sheet out of range" );
784 0 : if( nScTab < mnScCnt )
785 0 : ::set_flag( maTabInfoVec[ nScTab ].mnFlags, nFlags, bSet );
786 0 : }
787 :
788 0 : void XclExpTabInfo::CalcXclIndexes()
789 : {
790 0 : sal_uInt16 nXclTab = 0;
791 0 : SCTAB nScTab = 0;
792 :
793 : // --- pass 1: process regular sheets ---
794 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
795 : {
796 0 : if( IsExportTab( nScTab ) )
797 : {
798 0 : maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
799 0 : ++nXclTab;
800 : }
801 : else
802 0 : maTabInfoVec[ nScTab ].mnXclTab = EXC_TAB_DELETED;
803 : }
804 0 : mnXclCnt = nXclTab;
805 :
806 : // --- pass 2: process external sheets (nXclTab continues) ---
807 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
808 : {
809 0 : if( IsExternalTab( nScTab ) )
810 : {
811 0 : maTabInfoVec[ nScTab ].mnXclTab = nXclTab;
812 0 : ++nXclTab;
813 0 : ++mnXclExtCnt;
814 : }
815 : }
816 :
817 : // result: first occur all exported sheets, followed by all external sheets
818 0 : }
819 :
820 : typedef ::std::pair< OUString, SCTAB > XclExpTabName;
821 : typedef ::std::vector< XclExpTabName > XclExpTabNameVec;
822 :
823 : inline bool operator<( const XclExpTabName& rArg1, const XclExpTabName& rArg2 )
824 : {
825 : // compare the sheet names only
826 : return ScGlobal::GetCollator()->compareString( rArg1.first, rArg2.first ) < 0;
827 : }
828 :
829 0 : void XclExpTabInfo::CalcSortedIndexes()
830 : {
831 0 : ScDocument& rDoc = GetDoc();
832 0 : XclExpTabNameVec aVec( mnScCnt );
833 : SCTAB nScTab;
834 :
835 : // fill with sheet names
836 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
837 : {
838 0 : rDoc.GetName( nScTab, aVec[ nScTab ].first );
839 0 : aVec[ nScTab ].second = nScTab;
840 : }
841 0 : ::std::sort( aVec.begin(), aVec.end() );
842 :
843 : // fill index vectors from sorted sheet name vector
844 0 : maFromSortedVec.resize( mnScCnt );
845 0 : maToSortedVec.resize( mnScCnt );
846 0 : for( nScTab = 0; nScTab < mnScCnt; ++nScTab )
847 : {
848 0 : maFromSortedVec[ nScTab ] = aVec[ nScTab ].second;
849 0 : maToSortedVec[ aVec[ nScTab ].second ] = nScTab;
850 0 : }
851 0 : }
852 :
853 : // External names =============================================================
854 :
855 0 : XclExpExtNameBase::XclExpExtNameBase(
856 : const XclExpRoot& rRoot, const OUString& rName, sal_uInt16 nFlags ) :
857 : XclExpRecord( EXC_ID_EXTERNNAME ),
858 : XclExpRoot( rRoot ),
859 : maName( rName ),
860 : mxName( XclExpStringHelper::CreateString( rRoot, rName, EXC_STR_8BITLENGTH ) ),
861 0 : mnFlags( nFlags )
862 : {
863 : OSL_ENSURE( maName.getLength() <= 255, "XclExpExtNameBase::XclExpExtNameBase - string too long" );
864 0 : SetRecSize( 6 + mxName->GetSize() );
865 0 : }
866 :
867 0 : XclExpExtNameBase::~XclExpExtNameBase()
868 : {
869 0 : }
870 :
871 0 : void XclExpExtNameBase::WriteBody( XclExpStream& rStrm )
872 : {
873 0 : rStrm << mnFlags
874 0 : << sal_uInt32( 0 )
875 0 : << *mxName;
876 0 : WriteAddData( rStrm );
877 0 : }
878 :
879 0 : void XclExpExtNameBase::WriteAddData( XclExpStream& /*rStrm*/ )
880 : {
881 0 : }
882 :
883 0 : XclExpExtNameAddIn::XclExpExtNameAddIn( const XclExpRoot& rRoot, const OUString& rName ) :
884 0 : XclExpExtNameBase( rRoot, rName )
885 : {
886 0 : AddRecSize( 4 );
887 0 : }
888 :
889 0 : void XclExpExtNameAddIn::WriteAddData( XclExpStream& rStrm )
890 : {
891 : // write a #REF! error formula
892 0 : rStrm << sal_uInt16( 2 ) << EXC_TOKID_ERR << EXC_ERR_REF;
893 0 : }
894 :
895 0 : XclExpExtNameDde::XclExpExtNameDde( const XclExpRoot& rRoot,
896 : const OUString& rName, sal_uInt16 nFlags, const ScMatrix* pResults ) :
897 0 : XclExpExtNameBase( rRoot, rName, nFlags )
898 : {
899 0 : if( pResults )
900 : {
901 0 : mxMatrix.reset( new XclExpCachedMatrix( *pResults ) );
902 0 : AddRecSize( mxMatrix->GetSize() );
903 : }
904 0 : }
905 :
906 0 : void XclExpExtNameDde::WriteAddData( XclExpStream& rStrm )
907 : {
908 0 : if( mxMatrix )
909 0 : mxMatrix->Save( rStrm );
910 0 : }
911 :
912 0 : XclExpExtName::XclExpExtName( const XclExpRoot& rRoot, const XclExpSupbook& rSupbook,
913 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray ) :
914 : XclExpExtNameBase( rRoot, rName ),
915 : mrSupbook(rSupbook),
916 0 : mpArray(pArray->Clone())
917 : {
918 0 : }
919 :
920 0 : void XclExpExtName::WriteAddData( XclExpStream& rStrm )
921 : {
922 : // Write only if it only has a single token that is either a cell or cell
923 : // range address. Excel just writes '02 00 1C 17' for all the other types
924 : // of external names.
925 :
926 : using namespace ::formula;
927 : do
928 : {
929 0 : if (mpArray->GetLen() != 1)
930 0 : break;
931 :
932 0 : const ScToken* p = static_cast<const ScToken*>(mpArray->First());
933 0 : if (!p->IsExternalRef())
934 0 : break;
935 :
936 0 : switch (p->GetType())
937 : {
938 : case svExternalSingleRef:
939 : {
940 0 : const ScSingleRefData& rRef = p->GetSingleRef();
941 0 : if (rRef.IsTabRel())
942 0 : break;
943 :
944 0 : bool bColRel = rRef.IsColRel();
945 0 : bool bRowRel = rRef.IsRowRel();
946 0 : sal_uInt16 nCol = static_cast<sal_uInt16>(rRef.Col());
947 0 : sal_uInt16 nRow = static_cast<sal_uInt16>(rRef.Row());
948 0 : if (bColRel) nCol |= 0x4000;
949 0 : if (bRowRel) nCol |= 0x8000;
950 :
951 0 : OUString aTabName = p->GetString().getString();
952 0 : sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
953 :
954 : // size is always 9
955 0 : rStrm << static_cast<sal_uInt16>(9);
956 : // operator token (3A for cell reference)
957 0 : rStrm << static_cast<sal_uInt8>(0x3A);
958 : // cell address (Excel's address has 2 sheet IDs.)
959 0 : rStrm << nSBTab << nSBTab << nRow << nCol;
960 0 : return;
961 : }
962 : case svExternalDoubleRef:
963 : {
964 0 : const ScComplexRefData& rRef = p->GetDoubleRef();
965 0 : const ScSingleRefData& r1 = rRef.Ref1;
966 0 : const ScSingleRefData& r2 = rRef.Ref2;
967 0 : if (r1.IsTabRel() || r2.IsTabRel())
968 0 : break;
969 :
970 0 : sal_uInt16 nTab1 = r1.Tab();
971 0 : sal_uInt16 nTab2 = r2.Tab();
972 0 : bool bCol1Rel = r1.IsColRel();
973 0 : bool bRow1Rel = r1.IsRowRel();
974 0 : bool bCol2Rel = r2.IsColRel();
975 0 : bool bRow2Rel = r2.IsRowRel();
976 :
977 0 : sal_uInt16 nCol1 = static_cast<sal_uInt16>(r1.Col());
978 0 : sal_uInt16 nCol2 = static_cast<sal_uInt16>(r2.Col());
979 0 : sal_uInt16 nRow1 = static_cast<sal_uInt16>(r1.Row());
980 0 : sal_uInt16 nRow2 = static_cast<sal_uInt16>(r2.Row());
981 0 : if (bCol1Rel) nCol1 |= 0x4000;
982 0 : if (bRow1Rel) nCol1 |= 0x8000;
983 0 : if (bCol2Rel) nCol2 |= 0x4000;
984 0 : if (bRow2Rel) nCol2 |= 0x8000;
985 :
986 0 : OUString aTabName = p->GetString().getString();
987 0 : sal_uInt16 nSBTab = mrSupbook.GetTabIndex(aTabName);
988 :
989 : // size is always 13 (0x0D)
990 0 : rStrm << static_cast<sal_uInt16>(13);
991 : // operator token (3B for area reference)
992 0 : rStrm << static_cast<sal_uInt8>(0x3B);
993 : // range (area) address
994 0 : sal_uInt16 nSBTab2 = nSBTab + nTab2 - nTab1;
995 0 : rStrm << nSBTab << nSBTab2 << nRow1 << nRow2 << nCol1 << nCol2;
996 0 : return;
997 : }
998 : default:
999 : ; // nothing
1000 : }
1001 : }
1002 : while (false);
1003 :
1004 : // special value for #REF! (02 00 1C 17)
1005 0 : rStrm << static_cast<sal_uInt16>(2) << EXC_TOKID_ERR << EXC_ERR_REF;
1006 : }
1007 :
1008 : // List of external names =====================================================
1009 :
1010 0 : XclExpExtNameBuffer::XclExpExtNameBuffer( const XclExpRoot& rRoot ) :
1011 0 : XclExpRoot( rRoot )
1012 : {
1013 0 : }
1014 :
1015 0 : sal_uInt16 XclExpExtNameBuffer::InsertAddIn( const OUString& rName )
1016 : {
1017 0 : sal_uInt16 nIndex = GetIndex( rName );
1018 0 : return nIndex ? nIndex : AppendNew( new XclExpExtNameAddIn( GetRoot(), rName ) );
1019 : }
1020 :
1021 0 : sal_uInt16 XclExpExtNameBuffer::InsertEuroTool( const OUString& rName )
1022 : {
1023 0 : sal_uInt16 nIndex = GetIndex( rName );
1024 0 : return nIndex ? nIndex : AppendNew( new XclExpExtNameBase( GetRoot(), rName ) );
1025 : }
1026 :
1027 0 : sal_uInt16 XclExpExtNameBuffer::InsertDde(
1028 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1029 : {
1030 0 : sal_uInt16 nIndex = GetIndex( rItem );
1031 0 : if( nIndex == 0 )
1032 : {
1033 : size_t nPos;
1034 0 : if( GetDoc().FindDdeLink( rApplic, rTopic, rItem, SC_DDE_IGNOREMODE, nPos ) )
1035 : {
1036 : // create the leading 'StdDocumentName' EXTERNNAME record
1037 0 : if( maNameList.IsEmpty() )
1038 : AppendNew( new XclExpExtNameDde(
1039 0 : GetRoot(), OUString("StdDocumentName"), EXC_EXTN_EXPDDE_STDDOC ) );
1040 :
1041 : // try to find DDE result array, but create EXTERNNAME record without them too
1042 0 : const ScMatrix* pScMatrix = GetDoc().GetDdeLinkResultMatrix( nPos );
1043 0 : nIndex = AppendNew( new XclExpExtNameDde( GetRoot(), rItem, EXC_EXTN_EXPDDE, pScMatrix ) );
1044 : }
1045 : }
1046 0 : return nIndex;
1047 : }
1048 :
1049 0 : sal_uInt16 XclExpExtNameBuffer::InsertExtName( const XclExpSupbook& rSupbook,
1050 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray )
1051 : {
1052 0 : sal_uInt16 nIndex = GetIndex( rName );
1053 0 : return nIndex ? nIndex : AppendNew( new XclExpExtName( GetRoot(), rSupbook, rName, pArray ) );
1054 : }
1055 :
1056 0 : void XclExpExtNameBuffer::Save( XclExpStream& rStrm )
1057 : {
1058 0 : maNameList.Save( rStrm );
1059 0 : }
1060 :
1061 0 : sal_uInt16 XclExpExtNameBuffer::GetIndex( const OUString& rName ) const
1062 : {
1063 0 : for( size_t nPos = 0, nSize = maNameList.GetSize(); nPos < nSize; ++nPos )
1064 0 : if( maNameList.GetRecord( nPos )->GetName() == rName )
1065 0 : return static_cast< sal_uInt16 >( nPos + 1 );
1066 0 : return 0;
1067 : }
1068 :
1069 0 : sal_uInt16 XclExpExtNameBuffer::AppendNew( XclExpExtNameBase* pExtName )
1070 : {
1071 0 : XclExpExtNameRef xExtName( pExtName );
1072 0 : size_t nSize = maNameList.GetSize();
1073 0 : if( nSize < 0x7FFF )
1074 : {
1075 0 : maNameList.AppendRecord( xExtName );
1076 0 : return static_cast< sal_uInt16 >( nSize + 1 );
1077 : }
1078 0 : return 0;
1079 : }
1080 :
1081 : // Cached external cells ======================================================
1082 :
1083 0 : XclExpCrn::XclExpCrn( SCCOL nScCol, SCROW nScRow, const Any& rValue ) :
1084 : XclExpRecord( EXC_ID_CRN, 4 ),
1085 : mnScCol( nScCol ),
1086 0 : mnScRow( nScRow )
1087 : {
1088 0 : maValues.push_back( rValue );
1089 0 : }
1090 :
1091 0 : bool XclExpCrn::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1092 : {
1093 0 : if( (nScRow != mnScRow) || (nScCol != static_cast< SCCOL >( mnScCol + maValues.size() )) )
1094 0 : return false;
1095 0 : maValues.push_back( rValue );
1096 0 : return true;
1097 : }
1098 :
1099 0 : void XclExpCrn::WriteBody( XclExpStream& rStrm )
1100 : {
1101 0 : rStrm << static_cast< sal_uInt8 >( mnScCol + maValues.size() - 1 )
1102 0 : << static_cast< sal_uInt8 >( mnScCol )
1103 0 : << static_cast< sal_uInt16 >( mnScRow );
1104 0 : for( CachedValues::iterator aIt = maValues.begin(), aEnd = maValues.end(); aIt != aEnd; ++aIt )
1105 : {
1106 0 : if( aIt->has< bool >() )
1107 0 : WriteBool( rStrm, aIt->get< bool >() );
1108 0 : else if( aIt->has< double >() )
1109 0 : WriteDouble( rStrm, aIt->get< double >() );
1110 0 : else if( aIt->has< OUString >() )
1111 0 : WriteString( rStrm, aIt->get< OUString >() );
1112 : else
1113 0 : WriteEmpty( rStrm );
1114 : }
1115 0 : }
1116 :
1117 0 : void XclExpCrn::WriteBool( XclExpStream& rStrm, bool bValue )
1118 : {
1119 0 : rStrm << EXC_CACHEDVAL_BOOL << sal_uInt8( bValue ? 1 : 0);
1120 0 : rStrm.WriteZeroBytes( 7 );
1121 0 : }
1122 :
1123 0 : void XclExpCrn::WriteDouble( XclExpStream& rStrm, double fValue )
1124 : {
1125 0 : if( ::rtl::math::isNan( fValue ) )
1126 : {
1127 0 : sal_uInt16 nScError = static_cast< sal_uInt16 >( reinterpret_cast< const sal_math_Double* >( &fValue )->nan_parts.fraction_lo );
1128 0 : WriteError( rStrm, XclTools::GetXclErrorCode( nScError ) );
1129 : }
1130 : else
1131 : {
1132 0 : rStrm << EXC_CACHEDVAL_DOUBLE << fValue;
1133 : }
1134 0 : }
1135 :
1136 0 : void XclExpCrn::WriteString( XclExpStream& rStrm, const OUString& rValue )
1137 : {
1138 0 : rStrm << EXC_CACHEDVAL_STRING << XclExpString( rValue );
1139 0 : }
1140 :
1141 0 : void XclExpCrn::WriteError( XclExpStream& rStrm, sal_uInt8 nErrCode )
1142 : {
1143 0 : rStrm << EXC_CACHEDVAL_ERROR << nErrCode;
1144 0 : rStrm.WriteZeroBytes( 7 );
1145 0 : }
1146 :
1147 0 : void XclExpCrn::WriteEmpty( XclExpStream& rStrm )
1148 : {
1149 0 : rStrm << EXC_CACHEDVAL_EMPTY;
1150 0 : rStrm.WriteZeroBytes( 8 );
1151 0 : }
1152 :
1153 : // Cached cells of a sheet ====================================================
1154 :
1155 0 : XclExpXct::XclExpXct( const XclExpRoot& rRoot, const OUString& rTabName,
1156 : sal_uInt16 nSBTab, ScExternalRefCache::TableTypeRef xCacheTable ) :
1157 : XclExpRoot( rRoot ),
1158 : mxCacheTable( xCacheTable ),
1159 : maBoundRange( ScAddress::INITIALIZE_INVALID ),
1160 : maTabName( rTabName ),
1161 0 : mnSBTab( nSBTab )
1162 : {
1163 0 : }
1164 :
1165 0 : void XclExpXct::StoreCellRange( const ScRange& rRange )
1166 : {
1167 : // #i70418# restrict size of external range to prevent memory overflow
1168 0 : if( (rRange.aEnd.Col() - rRange.aStart.Col()) * (rRange.aEnd.Row() - rRange.aStart.Row()) > 1024 )
1169 0 : return;
1170 :
1171 0 : maUsedCells.SetMultiMarkArea( rRange );
1172 0 : maBoundRange.ExtendTo( rRange );
1173 : }
1174 :
1175 0 : void XclExpXct::StoreCell( const ScAddress& rCell, const ::formula::FormulaToken& rToken )
1176 : {
1177 0 : maUsedCells.SetMultiMarkArea( ScRange( rCell ) );
1178 0 : maBoundRange.ExtendTo( ScRange( rCell ) );
1179 : (void)rToken;
1180 0 : }
1181 :
1182 0 : void XclExpXct::StoreCellRange( const ScRange& rRange, const ::formula::FormulaToken& rToken )
1183 : {
1184 0 : maUsedCells.SetMultiMarkArea( rRange );
1185 0 : maBoundRange.ExtendTo( rRange );
1186 : (void)rToken;
1187 0 : }
1188 :
1189 : namespace {
1190 :
1191 0 : class XclExpCrnList : public XclExpRecordList< XclExpCrn >
1192 : {
1193 : public:
1194 : /** Inserts the passed value into an existing or new CRN record.
1195 : @return True = value inserted successfully, false = CRN list is full. */
1196 : bool InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue );
1197 : };
1198 :
1199 0 : bool XclExpCrnList::InsertValue( SCCOL nScCol, SCROW nScRow, const Any& rValue )
1200 : {
1201 0 : RecordRefType xLastRec = GetLastRecord();
1202 0 : if( xLastRec && xLastRec->InsertValue( nScCol, nScRow, rValue ) )
1203 0 : return true;
1204 0 : if( GetSize() == SAL_MAX_UINT16 )
1205 0 : return false;
1206 0 : AppendNewRecord( new XclExpCrn( nScCol, nScRow, rValue ) );
1207 0 : return true;
1208 : }
1209 :
1210 : } // namespace
1211 :
1212 0 : void XclExpXct::Save( XclExpStream& rStrm )
1213 : {
1214 0 : if( !mxCacheTable )
1215 0 : return;
1216 :
1217 : /* Get the range of used rows in the cache table. This may help to
1218 : optimize building the CRN record list if the cache table does not
1219 : contain all referred cells, e.g. if big empty ranges are used in the
1220 : formulas. */
1221 0 : ::std::pair< SCROW, SCROW > aRowRange = mxCacheTable->getRowRange();
1222 0 : if( aRowRange.first >= aRowRange.second )
1223 0 : return;
1224 :
1225 : /* Crop the bounding range of used cells in this table to Excel limits.
1226 : Return if there is no external cell inside these limits. */
1227 0 : if( !GetAddressConverter().ValidateRange( maBoundRange, false ) )
1228 0 : return;
1229 :
1230 : /* Find the resulting row range that needs to be processed. */
1231 0 : SCROW nScRow1 = ::std::max( aRowRange.first, maBoundRange.aStart.Row() );
1232 0 : SCROW nScRow2 = ::std::min( aRowRange.second - 1, maBoundRange.aEnd.Row() );
1233 0 : if( nScRow1 > nScRow2 )
1234 0 : return;
1235 :
1236 : /* Build and collect all CRN records before writing the XCT record. This
1237 : is needed to determine the total number of CRN records which must be
1238 : known when writing the XCT record (possibly encrypted, so seeking the
1239 : output strem back after writing the CRN records is not an option). */
1240 0 : XclExpCrnList aCrnRecs;
1241 0 : SvNumberFormatter& rFormatter = GetFormatter();
1242 0 : bool bValid = true;
1243 0 : for( SCROW nScRow = nScRow1; bValid && (nScRow <= nScRow2); ++nScRow )
1244 : {
1245 0 : ::std::pair< SCCOL, SCCOL > aColRange = mxCacheTable->getColRange( nScRow );
1246 0 : for( SCCOL nScCol = aColRange.first; bValid && (nScCol < aColRange.second); ++nScCol )
1247 : {
1248 0 : if( maUsedCells.IsCellMarked( nScCol, nScRow, true ) )
1249 : {
1250 0 : sal_uInt32 nScNumFmt = 0;
1251 0 : ScExternalRefCache::TokenRef xToken = mxCacheTable->getCell( nScCol, nScRow, &nScNumFmt );
1252 : using namespace ::formula;
1253 0 : if( xToken.get() ) switch( xToken->GetType() )
1254 : {
1255 : case svDouble:
1256 0 : bValid = (rFormatter.GetType( nScNumFmt ) == NUMBERFORMAT_LOGICAL) ?
1257 0 : aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() != 0 ) ) :
1258 0 : aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetDouble() ) );
1259 0 : break;
1260 : case svString:
1261 : // do not save empty strings (empty cells) to cache
1262 0 : if( !xToken->GetString().isEmpty() )
1263 0 : bValid = aCrnRecs.InsertValue( nScCol, nScRow, Any( xToken->GetString().getString() ) );
1264 0 : break;
1265 : default:
1266 0 : break;
1267 0 : }
1268 : }
1269 : }
1270 : }
1271 :
1272 : // write the XCT record and the list of CRN records
1273 0 : rStrm.StartRecord( EXC_ID_XCT, 4 );
1274 0 : rStrm << static_cast< sal_uInt16 >( aCrnRecs.GetSize() ) << mnSBTab;
1275 0 : rStrm.EndRecord();
1276 0 : aCrnRecs.Save( rStrm );
1277 : }
1278 :
1279 : // External documents (EXTERNSHEET/SUPBOOK), base class =======================
1280 :
1281 0 : XclExpExternSheetBase::XclExpExternSheetBase( const XclExpRoot& rRoot, sal_uInt16 nRecId, sal_uInt32 nRecSize ) :
1282 : XclExpRecord( nRecId, nRecSize ),
1283 0 : XclExpRoot( rRoot )
1284 : {
1285 0 : }
1286 :
1287 0 : XclExpExtNameBuffer& XclExpExternSheetBase::GetExtNameBuffer()
1288 : {
1289 0 : if( !mxExtNameBfr )
1290 0 : mxExtNameBfr.reset( new XclExpExtNameBuffer( GetRoot() ) );
1291 0 : return *mxExtNameBfr;
1292 : }
1293 :
1294 0 : void XclExpExternSheetBase::WriteExtNameBuffer( XclExpStream& rStrm )
1295 : {
1296 0 : if( mxExtNameBfr )
1297 0 : mxExtNameBfr->Save( rStrm );
1298 0 : }
1299 :
1300 : // External documents (EXTERNSHEET, BIFF5/BIFF7) ==============================
1301 :
1302 0 : XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, sal_Unicode cCode ) :
1303 0 : XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1304 : {
1305 0 : Init( OUString(cCode) );
1306 0 : }
1307 :
1308 0 : XclExpExternSheet::XclExpExternSheet( const XclExpRoot& rRoot, const OUString& rTabName ) :
1309 0 : XclExpExternSheetBase( rRoot, EXC_ID_EXTERNSHEET )
1310 : {
1311 : // reference to own sheet: \03<sheetname>
1312 0 : Init(OUString(EXC_EXTSH_TABNAME) + rTabName);
1313 0 : }
1314 :
1315 0 : void XclExpExternSheet::Save( XclExpStream& rStrm )
1316 : {
1317 : // EXTERNSHEET record
1318 0 : XclExpRecord::Save( rStrm );
1319 : // EXTERNNAME records
1320 0 : WriteExtNameBuffer( rStrm );
1321 0 : }
1322 :
1323 0 : void XclExpExternSheet::Init( const OUString& rEncUrl )
1324 : {
1325 : OSL_ENSURE_BIFF( GetBiff() <= EXC_BIFF5 );
1326 0 : maTabName.AssignByte( rEncUrl, GetTextEncoding(), EXC_STR_8BITLENGTH );
1327 0 : SetRecSize( maTabName.GetSize() );
1328 0 : }
1329 :
1330 0 : sal_uInt16 XclExpExternSheet::InsertAddIn( const OUString& rName )
1331 : {
1332 0 : return GetExtNameBuffer().InsertAddIn( rName );
1333 : }
1334 :
1335 0 : void XclExpExternSheet::WriteBody( XclExpStream& rStrm )
1336 : {
1337 0 : sal_uInt8 nNameSize = static_cast< sal_uInt8 >( maTabName.Len() );
1338 : // special case: reference to own sheet (starting with '\03') needs wrong string length
1339 0 : if( maTabName.GetChar( 0 ) == EXC_EXTSH_TABNAME )
1340 0 : --nNameSize;
1341 0 : rStrm << nNameSize;
1342 0 : maTabName.WriteBuffer( rStrm );
1343 0 : }
1344 :
1345 : // External document (SUPBOOK, BIFF8) =========================================
1346 :
1347 0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, sal_uInt16 nXclTabCount ) :
1348 : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1349 : meType( EXC_SBTYPE_SELF ),
1350 0 : mnXclTabCount( nXclTabCount )
1351 : {
1352 0 : }
1353 :
1354 0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot ) :
1355 : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1356 : meType( EXC_SBTYPE_ADDIN ),
1357 0 : mnXclTabCount( 1 )
1358 : {
1359 0 : }
1360 :
1361 0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl, XclSupbookType ) :
1362 : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1363 : maUrl( rUrl ),
1364 : maUrlEncoded( rUrl ),
1365 : meType( EXC_SBTYPE_EUROTOOL ),
1366 0 : mnXclTabCount( 0 )
1367 : {
1368 0 : SetRecSize( 2 + maUrlEncoded.GetSize() );
1369 0 : }
1370 :
1371 :
1372 0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rUrl ) :
1373 : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK ),
1374 : maUrl( rUrl ),
1375 : maUrlEncoded( XclExpUrlHelper::EncodeUrl( rRoot, rUrl ) ),
1376 : meType( EXC_SBTYPE_EXTERN ),
1377 0 : mnXclTabCount( 0 )
1378 : {
1379 0 : SetRecSize( 2 + maUrlEncoded.GetSize() );
1380 :
1381 : // We need to create all tables up front to ensure the correct table order.
1382 0 : ScExternalRefManager* pRefMgr = rRoot.GetDoc().GetExternalRefManager();
1383 0 : sal_uInt16 nFileId = pRefMgr->getExternalFileId( rUrl );
1384 0 : ScfStringVec aTabNames;
1385 0 : pRefMgr->getAllCachedTableNames( nFileId, aTabNames );
1386 0 : for( ScfStringVec::const_iterator aBeg = aTabNames.begin(), aIt = aBeg, aEnd = aTabNames.end(); aIt != aEnd; ++aIt )
1387 0 : InsertTabName( *aIt, pRefMgr->getCacheTable( nFileId, aIt - aBeg ) );
1388 0 : }
1389 :
1390 0 : XclExpSupbook::XclExpSupbook( const XclExpRoot& rRoot, const OUString& rApplic, const OUString& rTopic ) :
1391 : XclExpExternSheetBase( rRoot, EXC_ID_SUPBOOK, 4 ),
1392 : maUrl( rApplic ),
1393 : maDdeTopic( rTopic ),
1394 : maUrlEncoded( XclExpUrlHelper::EncodeDde( rApplic, rTopic ) ),
1395 : meType( EXC_SBTYPE_SPECIAL ),
1396 0 : mnXclTabCount( 0 )
1397 : {
1398 0 : SetRecSize( 2 + maUrlEncoded.GetSize() );
1399 0 : }
1400 :
1401 0 : bool XclExpSupbook::IsUrlLink( const OUString& rUrl ) const
1402 : {
1403 0 : return (meType == EXC_SBTYPE_EXTERN || meType == EXC_SBTYPE_EUROTOOL) && (maUrl == rUrl);
1404 : }
1405 :
1406 0 : bool XclExpSupbook::IsDdeLink( const OUString& rApplic, const OUString& rTopic ) const
1407 : {
1408 0 : return (meType == EXC_SBTYPE_SPECIAL) && (maUrl == rApplic) && (maDdeTopic == rTopic);
1409 : }
1410 :
1411 0 : void XclExpSupbook::FillRefLogEntry( XclExpRefLogEntry& rRefLogEntry,
1412 : sal_uInt16 nFirstSBTab, sal_uInt16 nLastSBTab ) const
1413 : {
1414 0 : rRefLogEntry.mpUrl = maUrlEncoded.IsEmpty() ? 0 : &maUrlEncoded;
1415 0 : rRefLogEntry.mpFirstTab = GetTabName( nFirstSBTab );
1416 0 : rRefLogEntry.mpLastTab = GetTabName( nLastSBTab );
1417 0 : }
1418 :
1419 0 : void XclExpSupbook::StoreCellRange( const ScRange& rRange, sal_uInt16 nSBTab )
1420 : {
1421 0 : if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1422 0 : pXct->StoreCellRange( rRange );
1423 0 : }
1424 :
1425 0 : void XclExpSupbook::StoreCell( sal_uInt16 nSBTab, const ScAddress& rCell, const formula::FormulaToken& rToken )
1426 : {
1427 0 : if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1428 0 : pXct->StoreCell( rCell, rToken );
1429 0 : }
1430 :
1431 0 : void XclExpSupbook::StoreCellRange( sal_uInt16 nSBTab, const ScRange& rRange, const formula::FormulaToken& rToken )
1432 : {
1433 : // multi-table range is not allowed!
1434 0 : if( rRange.aStart.Tab() == rRange.aEnd.Tab() )
1435 0 : if( XclExpXct* pXct = maXctList.GetRecord( nSBTab ).get() )
1436 0 : pXct->StoreCellRange( rRange, rToken );
1437 0 : }
1438 :
1439 0 : sal_uInt16 XclExpSupbook::GetTabIndex( const OUString& rTabName ) const
1440 : {
1441 0 : XclExpString aXclName(rTabName);
1442 0 : size_t nSize = maXctList.GetSize();
1443 0 : for (size_t i = 0; i < nSize; ++i)
1444 : {
1445 0 : XclExpXctRef aRec = maXctList.GetRecord(i);
1446 0 : if (aXclName == aRec->GetTabName())
1447 0 : return ulimit_cast<sal_uInt16>(i);
1448 0 : }
1449 0 : return EXC_NOTAB;
1450 : }
1451 :
1452 0 : sal_uInt16 XclExpSupbook::GetTabCount() const
1453 : {
1454 0 : return ulimit_cast<sal_uInt16>(maXctList.GetSize());
1455 : }
1456 :
1457 0 : sal_uInt16 XclExpSupbook::InsertTabName( const OUString& rTabName, ScExternalRefCache::TableTypeRef xCacheTable )
1458 : {
1459 : OSL_ENSURE( meType == EXC_SBTYPE_EXTERN, "XclExpSupbook::InsertTabName - don't insert sheet names here" );
1460 0 : sal_uInt16 nSBTab = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1461 0 : XclExpXctRef xXct( new XclExpXct( GetRoot(), rTabName, nSBTab, xCacheTable ) );
1462 0 : AddRecSize( xXct->GetTabName().GetSize() );
1463 0 : maXctList.AppendRecord( xXct );
1464 0 : return nSBTab;
1465 : }
1466 :
1467 0 : sal_uInt16 XclExpSupbook::InsertAddIn( const OUString& rName )
1468 : {
1469 0 : return GetExtNameBuffer().InsertAddIn( rName );
1470 : }
1471 :
1472 0 : sal_uInt16 XclExpSupbook::InsertEuroTool( const OUString& rName )
1473 : {
1474 0 : return GetExtNameBuffer().InsertEuroTool( rName );
1475 : }
1476 :
1477 0 : sal_uInt16 XclExpSupbook::InsertDde( const OUString& rItem )
1478 : {
1479 0 : return GetExtNameBuffer().InsertDde( maUrl, maDdeTopic, rItem );
1480 : }
1481 :
1482 0 : sal_uInt16 XclExpSupbook::InsertExtName( const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray )
1483 : {
1484 0 : return GetExtNameBuffer().InsertExtName(*this, rName, pArray);
1485 : }
1486 :
1487 0 : void XclExpSupbook::Save( XclExpStream& rStrm )
1488 : {
1489 : // SUPBOOK record
1490 0 : XclExpRecord::Save( rStrm );
1491 : // XCT record, CRN records
1492 0 : maXctList.Save( rStrm );
1493 : // EXTERNNAME records
1494 0 : WriteExtNameBuffer( rStrm );
1495 0 : }
1496 :
1497 0 : const XclExpString* XclExpSupbook::GetTabName( sal_uInt16 nSBTab ) const
1498 : {
1499 0 : XclExpXctRef xXct = maXctList.GetRecord( nSBTab );
1500 0 : return xXct ? &xXct->GetTabName() : 0;
1501 : }
1502 :
1503 0 : void XclExpSupbook::WriteBody( XclExpStream& rStrm )
1504 : {
1505 0 : switch( meType )
1506 : {
1507 : case EXC_SBTYPE_SELF:
1508 0 : rStrm << mnXclTabCount << EXC_SUPB_SELF;
1509 0 : break;
1510 : case EXC_SBTYPE_EXTERN:
1511 : case EXC_SBTYPE_SPECIAL:
1512 : case EXC_SBTYPE_EUROTOOL:
1513 : {
1514 0 : sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXctList.GetSize() );
1515 0 : rStrm << nCount << maUrlEncoded;
1516 :
1517 0 : for( size_t nPos = 0, nSize = maXctList.GetSize(); nPos < nSize; ++nPos )
1518 0 : rStrm << maXctList.GetRecord( nPos )->GetTabName();
1519 : }
1520 0 : break;
1521 : case EXC_SBTYPE_ADDIN:
1522 0 : rStrm << mnXclTabCount << EXC_SUPB_ADDIN;
1523 0 : break;
1524 : default:
1525 : OSL_FAIL( "XclExpSupbook::WriteBody - unknown SUPBOOK type" );
1526 : }
1527 0 : }
1528 :
1529 : // All SUPBOOKS in a document =================================================
1530 :
1531 0 : XclExpSupbookBuffer::XclExpSupbookBuffer( const XclExpRoot& rRoot ) :
1532 : XclExpRoot( rRoot ),
1533 : mnOwnDocSB( SAL_MAX_UINT16 ),
1534 0 : mnAddInSB( SAL_MAX_UINT16 )
1535 : {
1536 0 : XclExpTabInfo& rTabInfo = GetTabInfo();
1537 0 : sal_uInt16 nXclCnt = rTabInfo.GetXclTabCount();
1538 0 : sal_uInt16 nCodeCnt = static_cast< sal_uInt16 >( GetExtDocOptions().GetCodeNameCount() );
1539 0 : size_t nCount = nXclCnt + rTabInfo.GetXclExtTabCount();
1540 :
1541 : OSL_ENSURE( nCount > 0, "XclExpSupbookBuffer::XclExpSupbookBuffer - no sheets to export" );
1542 0 : if( nCount )
1543 : {
1544 0 : maSBIndexVec.resize( nCount );
1545 :
1546 : // self-ref SUPBOOK first of list
1547 0 : XclExpSupbookRef xSupbook( new XclExpSupbook( GetRoot(), ::std::max( nXclCnt, nCodeCnt ) ) );
1548 0 : mnOwnDocSB = Append( xSupbook );
1549 0 : for( sal_uInt16 nXclTab = 0; nXclTab < nXclCnt; ++nXclTab )
1550 0 : maSBIndexVec[ nXclTab ].Set( mnOwnDocSB, nXclTab );
1551 : }
1552 0 : }
1553 :
1554 0 : XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFirstXclTab, sal_uInt16 nLastXclTab,
1555 : XclExpRefLogEntry* pRefLogEntry ) const
1556 : {
1557 0 : XclExpXti aXti;
1558 0 : size_t nSize = maSBIndexVec.size();
1559 0 : if( (nFirstXclTab < nSize) && (nLastXclTab < nSize) )
1560 : {
1561 : // index of the SUPBOOK record
1562 0 : aXti.mnSupbook = maSBIndexVec[ nFirstXclTab ].mnSupbook;
1563 :
1564 : // all sheets in the same supbook?
1565 0 : bool bSameSB = true;
1566 0 : for( sal_uInt16 nXclTab = nFirstXclTab + 1; bSameSB && (nXclTab <= nLastXclTab); ++nXclTab )
1567 : {
1568 0 : bSameSB = maSBIndexVec[ nXclTab ].mnSupbook == aXti.mnSupbook;
1569 0 : if( !bSameSB )
1570 0 : nLastXclTab = nXclTab - 1;
1571 : }
1572 0 : aXti.mnFirstSBTab = maSBIndexVec[ nFirstXclTab ].mnSBTab;
1573 0 : aXti.mnLastSBTab = maSBIndexVec[ nLastXclTab ].mnSBTab;
1574 :
1575 : // fill external reference log entry (for change tracking)
1576 0 : if( pRefLogEntry )
1577 : {
1578 0 : pRefLogEntry->mnFirstXclTab = nFirstXclTab;
1579 0 : pRefLogEntry->mnLastXclTab = nLastXclTab;
1580 0 : XclExpSupbookRef xSupbook = maSupbookList.GetRecord( aXti.mnSupbook );
1581 0 : if( xSupbook )
1582 0 : xSupbook->FillRefLogEntry( *pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab );
1583 0 : }
1584 : }
1585 : else
1586 : {
1587 : // special range, i.e. for deleted sheets or add-ins
1588 0 : aXti.mnSupbook = mnOwnDocSB;
1589 0 : aXti.mnFirstSBTab = nFirstXclTab;
1590 0 : aXti.mnLastSBTab = nLastXclTab;
1591 : }
1592 :
1593 0 : return aXti;
1594 : }
1595 :
1596 0 : void XclExpSupbookBuffer::StoreCellRange( const ScRange& rRange )
1597 : {
1598 0 : sal_uInt16 nXclTab = GetTabInfo().GetXclTab( rRange.aStart.Tab() );
1599 0 : if( nXclTab < maSBIndexVec.size() )
1600 : {
1601 0 : const XclExpSBIndex& rSBIndex = maSBIndexVec[ nXclTab ];
1602 0 : XclExpSupbookRef xSupbook = maSupbookList.GetRecord( rSBIndex.mnSupbook );
1603 : OSL_ENSURE( xSupbook , "XclExpSupbookBuffer::StoreCellRange - missing SUPBOOK record" );
1604 0 : if( xSupbook )
1605 0 : xSupbook->StoreCellRange( rRange, rSBIndex.mnSBTab );
1606 : }
1607 0 : }
1608 :
1609 : namespace {
1610 :
1611 : class FindSBIndexEntry
1612 : {
1613 : public:
1614 0 : explicit FindSBIndexEntry(sal_uInt16 nSupbookId, sal_uInt16 nTabId) :
1615 0 : mnSupbookId(nSupbookId), mnTabId(nTabId) {}
1616 :
1617 0 : bool operator()(const XclExpSupbookBuffer::XclExpSBIndex& r) const
1618 : {
1619 0 : return mnSupbookId == r.mnSupbook && mnTabId == r.mnSBTab;
1620 : }
1621 :
1622 : private:
1623 : sal_uInt16 mnSupbookId;
1624 : sal_uInt16 mnTabId;
1625 : };
1626 :
1627 : }
1628 :
1629 0 : void XclExpSupbookBuffer::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rCell )
1630 : {
1631 0 : ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1632 0 : const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1633 0 : if (!pUrl)
1634 0 : return;
1635 :
1636 0 : XclExpSupbookRef xSupbook;
1637 : sal_uInt16 nSupbookId;
1638 0 : if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1639 : {
1640 0 : xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1641 0 : nSupbookId = Append(xSupbook);
1642 : }
1643 :
1644 0 : ScExternalRefCache::TokenRef pToken = pRefMgr->getSingleRefToken(nFileId, rTabName, rCell, NULL, NULL);
1645 0 : if (!pToken.get())
1646 0 : return;
1647 :
1648 0 : sal_uInt16 nSheetId = xSupbook->GetTabIndex(rTabName);
1649 0 : if (nSheetId == EXC_NOTAB)
1650 : // specified table name not found in this SUPBOOK.
1651 0 : return;
1652 :
1653 0 : FindSBIndexEntry f(nSupbookId, nSheetId);
1654 0 : XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1655 0 : XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1656 0 : if (itr == itrEnd)
1657 : {
1658 0 : maSBIndexVec.push_back(XclExpSBIndex());
1659 0 : XclExpSBIndex& r = maSBIndexVec.back();
1660 0 : r.mnSupbook = nSupbookId;
1661 0 : r.mnSBTab = nSheetId;
1662 : }
1663 :
1664 0 : xSupbook->StoreCell(nSheetId, rCell, *pToken);
1665 : }
1666 :
1667 0 : void XclExpSupbookBuffer::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
1668 : {
1669 0 : ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1670 0 : const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1671 0 : if (!pUrl)
1672 0 : return;
1673 :
1674 0 : XclExpSupbookRef xSupbook;
1675 : sal_uInt16 nSupbookId;
1676 0 : if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1677 : {
1678 0 : xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1679 0 : nSupbookId = Append(xSupbook);
1680 : }
1681 :
1682 0 : SCTAB nTabCount = rRange.aEnd.Tab() - rRange.aStart.Tab() + 1;
1683 :
1684 : // If this is a multi-table range, get token for each table.
1685 : using namespace ::formula;
1686 0 : vector<FormulaToken*> aMatrixList;
1687 0 : aMatrixList.reserve(nTabCount);
1688 :
1689 : // This is a new'ed instance, so we must manage its life cycle here.
1690 0 : ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, rRange, NULL);
1691 0 : if (!pArray.get())
1692 0 : return;
1693 :
1694 0 : for (FormulaToken* p = pArray->First(); p; p = pArray->Next())
1695 : {
1696 0 : if (p->GetType() == svMatrix)
1697 0 : aMatrixList.push_back(p);
1698 0 : else if (p->GetOpCode() != ocSep)
1699 : {
1700 : // This is supposed to be ocSep!!!
1701 0 : return;
1702 : }
1703 : }
1704 :
1705 0 : if (aMatrixList.size() != static_cast<size_t>(nTabCount))
1706 : {
1707 : // matrix size mis-match !
1708 0 : return;
1709 : }
1710 :
1711 0 : sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1712 :
1713 0 : ScRange aRange(rRange);
1714 0 : aRange.aStart.SetTab(0);
1715 0 : aRange.aEnd.SetTab(0);
1716 0 : for (SCTAB nTab = 0; nTab < nTabCount; ++nTab)
1717 : {
1718 0 : sal_uInt16 nSheetId = nFirstSheetId + static_cast<sal_uInt16>(nTab);
1719 0 : FindSBIndexEntry f(nSupbookId, nSheetId);
1720 0 : XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1721 0 : XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1722 0 : if (itr == itrEnd)
1723 : {
1724 0 : maSBIndexVec.push_back(XclExpSBIndex());
1725 0 : XclExpSBIndex& r = maSBIndexVec.back();
1726 0 : r.mnSupbook = nSupbookId;
1727 0 : r.mnSBTab = nSheetId;
1728 : }
1729 :
1730 0 : xSupbook->StoreCellRange(nSheetId, aRange, *aMatrixList[nTab]);
1731 0 : }
1732 : }
1733 :
1734 0 : bool XclExpSupbookBuffer::InsertAddIn(
1735 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1736 : {
1737 0 : XclExpSupbookRef xSupbook;
1738 0 : if( mnAddInSB == SAL_MAX_UINT16 )
1739 : {
1740 0 : xSupbook.reset( new XclExpSupbook( GetRoot() ) );
1741 0 : mnAddInSB = Append( xSupbook );
1742 : }
1743 : else
1744 0 : xSupbook = maSupbookList.GetRecord( mnAddInSB );
1745 : OSL_ENSURE( xSupbook, "XclExpSupbookBuffer::InsertAddin - missing add-in supbook" );
1746 0 : rnSupbook = mnAddInSB;
1747 0 : rnExtName = xSupbook->InsertAddIn( rName );
1748 0 : return rnExtName > 0;
1749 : }
1750 :
1751 0 : bool XclExpSupbookBuffer::InsertEuroTool(
1752 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rName )
1753 : {
1754 0 : XclExpSupbookRef xSupbook;
1755 0 : OUString aUrl( "\001\010EUROTOOL.XLA" );
1756 0 : if( !GetSupbookUrl( xSupbook, rnSupbook, aUrl ) )
1757 : {
1758 0 : xSupbook.reset( new XclExpSupbook( GetRoot(), aUrl, EXC_SBTYPE_EUROTOOL ) );
1759 0 : rnSupbook = Append( xSupbook );
1760 : }
1761 0 : rnExtName = xSupbook->InsertEuroTool( rName );
1762 0 : return rnExtName > 0;
1763 : }
1764 :
1765 0 : bool XclExpSupbookBuffer::InsertDde(
1766 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName,
1767 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
1768 : {
1769 0 : XclExpSupbookRef xSupbook;
1770 0 : if( !GetSupbookDde( xSupbook, rnSupbook, rApplic, rTopic ) )
1771 : {
1772 0 : xSupbook.reset( new XclExpSupbook( GetRoot(), rApplic, rTopic ) );
1773 0 : rnSupbook = Append( xSupbook );
1774 : }
1775 0 : rnExtName = xSupbook->InsertDde( rItem );
1776 0 : return rnExtName > 0;
1777 : }
1778 :
1779 0 : bool XclExpSupbookBuffer::InsertExtName(
1780 : sal_uInt16& rnSupbook, sal_uInt16& rnExtName, const OUString& rUrl,
1781 : const OUString& rName, const ScExternalRefCache::TokenArrayRef pArray )
1782 : {
1783 0 : XclExpSupbookRef xSupbook;
1784 0 : if (!GetSupbookUrl(xSupbook, rnSupbook, rUrl))
1785 : {
1786 0 : xSupbook.reset( new XclExpSupbook(GetRoot(), rUrl) );
1787 0 : rnSupbook = Append(xSupbook);
1788 : }
1789 0 : rnExtName = xSupbook->InsertExtName(rName, pArray);
1790 0 : return rnExtName > 0;
1791 : }
1792 :
1793 0 : XclExpXti XclExpSupbookBuffer::GetXti( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
1794 : XclExpRefLogEntry* pRefLogEntry )
1795 : {
1796 0 : XclExpXti aXti(0, EXC_NOTAB, EXC_NOTAB);
1797 0 : ScExternalRefManager* pRefMgr = GetDoc().GetExternalRefManager();
1798 0 : const OUString* pUrl = pRefMgr->getExternalFileName(nFileId);
1799 0 : if (!pUrl)
1800 0 : return aXti;
1801 :
1802 0 : XclExpSupbookRef xSupbook;
1803 : sal_uInt16 nSupbookId;
1804 0 : if (!GetSupbookUrl(xSupbook, nSupbookId, *pUrl))
1805 : {
1806 0 : xSupbook.reset(new XclExpSupbook(GetRoot(), *pUrl));
1807 0 : nSupbookId = Append(xSupbook);
1808 : }
1809 0 : aXti.mnSupbook = nSupbookId;
1810 :
1811 0 : sal_uInt16 nFirstSheetId = xSupbook->GetTabIndex(rTabName);
1812 0 : if (nFirstSheetId == EXC_NOTAB)
1813 : {
1814 : // first sheet not found in SUPBOOK.
1815 0 : return aXti;
1816 : }
1817 0 : sal_uInt16 nSheetCount = xSupbook->GetTabCount();
1818 0 : for (sal_uInt16 i = 0; i < nXclTabSpan; ++i)
1819 : {
1820 0 : sal_uInt16 nSheetId = nFirstSheetId + i;
1821 0 : if (nSheetId >= nSheetCount)
1822 0 : return aXti;
1823 :
1824 0 : FindSBIndexEntry f(nSupbookId, nSheetId);
1825 0 : XclExpSBIndexVec::iterator itrEnd = maSBIndexVec.end();
1826 0 : XclExpSBIndexVec::const_iterator itr = find_if(maSBIndexVec.begin(), itrEnd, f);
1827 0 : if (itr == itrEnd)
1828 : {
1829 0 : maSBIndexVec.push_back(XclExpSBIndex());
1830 0 : XclExpSBIndex& r = maSBIndexVec.back();
1831 0 : r.mnSupbook = nSupbookId;
1832 0 : r.mnSBTab = nSheetId;
1833 : }
1834 0 : if (i == 0)
1835 0 : aXti.mnFirstSBTab = nSheetId;
1836 0 : if (i == nXclTabSpan - 1)
1837 0 : aXti.mnLastSBTab = nSheetId;
1838 : }
1839 :
1840 0 : if (pRefLogEntry)
1841 : {
1842 0 : pRefLogEntry->mnFirstXclTab = 0;
1843 0 : pRefLogEntry->mnLastXclTab = 0;
1844 0 : if (xSupbook)
1845 0 : xSupbook->FillRefLogEntry(*pRefLogEntry, aXti.mnFirstSBTab, aXti.mnLastSBTab);
1846 : }
1847 :
1848 0 : return aXti;
1849 : }
1850 :
1851 0 : void XclExpSupbookBuffer::Save( XclExpStream& rStrm )
1852 : {
1853 0 : maSupbookList.Save( rStrm );
1854 0 : }
1855 :
1856 0 : bool XclExpSupbookBuffer::GetSupbookUrl(
1857 : XclExpSupbookRef& rxSupbook, sal_uInt16& rnIndex, const OUString& rUrl ) const
1858 : {
1859 0 : for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
1860 : {
1861 0 : rxSupbook = maSupbookList.GetRecord( nPos );
1862 0 : if( rxSupbook->IsUrlLink( rUrl ) )
1863 : {
1864 0 : rnIndex = ulimit_cast< sal_uInt16 >( nPos );
1865 0 : return true;
1866 : }
1867 : }
1868 0 : return false;
1869 : }
1870 :
1871 0 : bool XclExpSupbookBuffer::GetSupbookDde( XclExpSupbookRef& rxSupbook,
1872 : sal_uInt16& rnIndex, const OUString& rApplic, const OUString& rTopic ) const
1873 : {
1874 0 : for( size_t nPos = 0, nSize = maSupbookList.GetSize(); nPos < nSize; ++nPos )
1875 : {
1876 0 : rxSupbook = maSupbookList.GetRecord( nPos );
1877 0 : if( rxSupbook->IsDdeLink( rApplic, rTopic ) )
1878 : {
1879 0 : rnIndex = ulimit_cast< sal_uInt16 >( nPos );
1880 0 : return true;
1881 : }
1882 : }
1883 0 : return false;
1884 : }
1885 :
1886 0 : sal_uInt16 XclExpSupbookBuffer::Append( XclExpSupbookRef xSupbook )
1887 : {
1888 0 : maSupbookList.AppendRecord( xSupbook );
1889 0 : return ulimit_cast< sal_uInt16 >( maSupbookList.GetSize() - 1 );
1890 : }
1891 :
1892 : // Export link manager ========================================================
1893 :
1894 0 : XclExpLinkManagerImpl::XclExpLinkManagerImpl( const XclExpRoot& rRoot ) :
1895 0 : XclExpRoot( rRoot )
1896 : {
1897 0 : }
1898 :
1899 0 : XclExpLinkManagerImpl5::XclExpLinkManagerImpl5( const XclExpRoot& rRoot ) :
1900 0 : XclExpLinkManagerImpl( rRoot )
1901 : {
1902 0 : }
1903 :
1904 0 : void XclExpLinkManagerImpl5::FindExtSheet(
1905 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
1906 : SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
1907 : {
1908 0 : FindInternal( rnExtSheet, rnFirstXclTab, nFirstScTab );
1909 0 : if( (rnFirstXclTab == EXC_TAB_DELETED) || (nFirstScTab == nLastScTab) )
1910 : {
1911 0 : rnLastXclTab = rnFirstXclTab;
1912 : }
1913 : else
1914 : {
1915 : sal_uInt16 nDummyExtSheet;
1916 0 : FindInternal( nDummyExtSheet, rnLastXclTab, nLastScTab );
1917 : }
1918 :
1919 : (void)pRefLogEntry; // avoid compiler warning
1920 : OSL_ENSURE( !pRefLogEntry, "XclExpLinkManagerImpl5::FindExtSheet - fill reflog entry not implemented" );
1921 0 : }
1922 :
1923 0 : sal_uInt16 XclExpLinkManagerImpl5::FindExtSheet( sal_Unicode cCode )
1924 : {
1925 : sal_uInt16 nExtSheet;
1926 0 : FindInternal( nExtSheet, cCode );
1927 0 : return nExtSheet;
1928 : }
1929 :
1930 0 : void XclExpLinkManagerImpl5::FindExtSheet(
1931 : sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, sal_uInt16 /*nXclTabSpan*/,
1932 : sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnFirstSBTab*/, sal_uInt16& /*rnLastSBTab*/,
1933 : XclExpRefLogEntry* /*pRefLogEntry*/ )
1934 : {
1935 : // not implemented
1936 0 : }
1937 :
1938 0 : void XclExpLinkManagerImpl5::StoreCellRange( const ScSingleRefData& /*rRef1*/, const ScSingleRefData& /*rRef2*/, const ScAddress& /*rPos*/ )
1939 : {
1940 : // not implemented
1941 0 : }
1942 :
1943 0 : void XclExpLinkManagerImpl5::StoreCell( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScAddress& /*rPos*/ )
1944 : {
1945 : // not implemented
1946 0 : }
1947 :
1948 0 : void XclExpLinkManagerImpl5::StoreCellRange( sal_uInt16 /*nFileId*/, const OUString& /*rTabName*/, const ScRange& /*rRange*/ )
1949 : {
1950 : // not implemented
1951 0 : }
1952 :
1953 0 : bool XclExpLinkManagerImpl5::InsertAddIn(
1954 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
1955 : {
1956 0 : XclExpExtSheetRef xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_ADDIN );
1957 0 : if( xExtSheet )
1958 : {
1959 0 : rnExtName = xExtSheet->InsertAddIn( rName );
1960 0 : return rnExtName > 0;
1961 : }
1962 0 : return false;
1963 : }
1964 :
1965 0 : bool XclExpLinkManagerImpl5::InsertEuroTool(
1966 : sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rName*/ )
1967 : {
1968 0 : return false;
1969 : }
1970 :
1971 :
1972 0 : bool XclExpLinkManagerImpl5::InsertDde(
1973 : sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/,
1974 : const OUString& /*rApplic*/, const OUString& /*rTopic*/, const OUString& /*rItem*/ )
1975 : {
1976 : // not implemented
1977 0 : return false;
1978 : }
1979 :
1980 0 : bool XclExpLinkManagerImpl5::InsertExtName(
1981 : sal_uInt16& /*rnExtSheet*/, sal_uInt16& /*rnExtName*/, const OUString& /*rUrl*/,
1982 : const OUString& /*rName*/, const ScExternalRefCache::TokenArrayRef /*pArray*/ )
1983 : {
1984 : // not implemented
1985 0 : return false;
1986 : }
1987 :
1988 0 : void XclExpLinkManagerImpl5::Save( XclExpStream& rStrm )
1989 : {
1990 0 : if( sal_uInt16 nExtSheetCount = GetExtSheetCount() )
1991 : {
1992 : // EXTERNCOUNT record
1993 0 : XclExpUInt16Record( EXC_ID_EXTERNCOUNT, nExtSheetCount ).Save( rStrm );
1994 : // list of EXTERNSHEET records with EXTERNNAME, XCT, CRN records
1995 0 : maExtSheetList.Save( rStrm );
1996 : }
1997 0 : }
1998 :
1999 0 : sal_uInt16 XclExpLinkManagerImpl5::GetExtSheetCount() const
2000 : {
2001 0 : return static_cast< sal_uInt16 >( maExtSheetList.GetSize() );
2002 : }
2003 :
2004 0 : sal_uInt16 XclExpLinkManagerImpl5::AppendInternal( XclExpExtSheetRef xExtSheet )
2005 : {
2006 0 : if( GetExtSheetCount() < 0x7FFF )
2007 : {
2008 0 : maExtSheetList.AppendRecord( xExtSheet );
2009 : // return negated one-based EXTERNSHEET index (i.e. 0xFFFD for 3rd record)
2010 0 : return static_cast< sal_uInt16 >( -GetExtSheetCount() );
2011 : }
2012 0 : return 0;
2013 : }
2014 :
2015 0 : void XclExpLinkManagerImpl5::CreateInternal()
2016 : {
2017 0 : if( maIntTabMap.empty() )
2018 : {
2019 : // create EXTERNSHEET records for all internal exported sheets
2020 0 : XclExpTabInfo& rTabInfo = GetTabInfo();
2021 0 : for( SCTAB nScTab = 0, nScCnt = rTabInfo.GetScTabCount(); nScTab < nScCnt; ++nScTab )
2022 : {
2023 0 : if( rTabInfo.IsExportTab( nScTab ) )
2024 : {
2025 0 : XclExpExtSheetRef xRec;
2026 0 : if( nScTab == GetCurrScTab() )
2027 0 : xRec.reset( new XclExpExternSheet( GetRoot(), EXC_EXTSH_OWNTAB ) );
2028 : else
2029 0 : xRec.reset( new XclExpExternSheet( GetRoot(), rTabInfo.GetScTabName( nScTab ) ) );
2030 0 : maIntTabMap[ nScTab ] = AppendInternal( xRec );
2031 : }
2032 : }
2033 : }
2034 0 : }
2035 :
2036 0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::GetInternal( sal_uInt16 nExtSheet )
2037 : {
2038 0 : return maExtSheetList.GetRecord( static_cast< sal_uInt16 >( -nExtSheet - 1 ) );
2039 : }
2040 :
2041 0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2042 : sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab, SCTAB nScTab )
2043 : {
2044 : // create internal EXTERNSHEET records on demand
2045 0 : CreateInternal();
2046 :
2047 : // try to find an EXTERNSHEET record - if not, return a "deleted sheet" reference
2048 0 : XclExpExtSheetRef xExtSheet;
2049 0 : XclExpIntTabMap::const_iterator aIt = maIntTabMap.find( nScTab );
2050 0 : if( aIt == maIntTabMap.end() )
2051 : {
2052 0 : xExtSheet = FindInternal( rnExtSheet, EXC_EXTSH_OWNDOC );
2053 0 : rnXclTab = EXC_TAB_DELETED;
2054 : }
2055 : else
2056 : {
2057 0 : rnExtSheet = aIt->second;
2058 0 : xExtSheet = GetInternal( rnExtSheet );
2059 0 : rnXclTab = GetTabInfo().GetXclTab( nScTab );
2060 : }
2061 0 : return xExtSheet;
2062 : }
2063 :
2064 0 : XclExpLinkManagerImpl5::XclExpExtSheetRef XclExpLinkManagerImpl5::FindInternal(
2065 : sal_uInt16& rnExtSheet, sal_Unicode cCode )
2066 : {
2067 0 : XclExpExtSheetRef xExtSheet;
2068 0 : XclExpCodeMap::const_iterator aIt = maCodeMap.find( cCode );
2069 0 : if( aIt == maCodeMap.end() )
2070 : {
2071 0 : xExtSheet.reset( new XclExpExternSheet( GetRoot(), cCode ) );
2072 0 : rnExtSheet = maCodeMap[ cCode ] = AppendInternal( xExtSheet );
2073 : }
2074 : else
2075 : {
2076 0 : rnExtSheet = aIt->second;
2077 0 : xExtSheet = GetInternal( rnExtSheet );
2078 : }
2079 0 : return xExtSheet;
2080 : }
2081 :
2082 0 : XclExpLinkManagerImpl8::XclExpLinkManagerImpl8( const XclExpRoot& rRoot ) :
2083 : XclExpLinkManagerImpl( rRoot ),
2084 0 : maSBBuffer( rRoot )
2085 : {
2086 0 : }
2087 :
2088 0 : void XclExpLinkManagerImpl8::FindExtSheet(
2089 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2090 : SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2091 : {
2092 0 : XclExpTabInfo& rTabInfo = GetTabInfo();
2093 0 : rnFirstXclTab = rTabInfo.GetXclTab( nFirstScTab );
2094 0 : rnLastXclTab = rTabInfo.GetXclTab( nLastScTab );
2095 0 : rnExtSheet = InsertXti( maSBBuffer.GetXti( rnFirstXclTab, rnLastXclTab, pRefLogEntry ) );
2096 0 : }
2097 :
2098 0 : sal_uInt16 XclExpLinkManagerImpl8::FindExtSheet( sal_Unicode cCode )
2099 : {
2100 : (void)cCode; // avoid compiler warning
2101 : OSL_ENSURE( (cCode == EXC_EXTSH_OWNDOC) || (cCode == EXC_EXTSH_ADDIN),
2102 : "XclExpLinkManagerImpl8::FindExtSheet - unknown externsheet code" );
2103 0 : return InsertXti( maSBBuffer.GetXti( EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2104 : }
2105 :
2106 0 : void XclExpLinkManagerImpl8::FindExtSheet(
2107 : sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2108 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2109 : XclExpRefLogEntry* pRefLogEntry )
2110 : {
2111 0 : XclExpXti aXti = maSBBuffer.GetXti(nFileId, rTabName, nXclTabSpan, pRefLogEntry);
2112 0 : rnExtSheet = InsertXti(aXti);
2113 0 : rnFirstSBTab = aXti.mnFirstSBTab;
2114 0 : rnLastSBTab = aXti.mnLastSBTab;
2115 0 : }
2116 :
2117 0 : void XclExpLinkManagerImpl8::StoreCellRange( const ScSingleRefData& rRef1, const ScSingleRefData& rRef2, const ScAddress& rPos )
2118 : {
2119 0 : ScAddress aAbs1 = rRef1.toAbs(rPos);
2120 0 : ScAddress aAbs2 = rRef2.toAbs(rPos);
2121 0 : if (!rRef1.IsDeleted() && !rRef2.IsDeleted() && (aAbs1.Tab() >= 0) && (aAbs2.Tab() >= 0))
2122 : {
2123 0 : const XclExpTabInfo& rTabInfo = GetTabInfo();
2124 0 : SCTAB nFirstScTab = aAbs1.Tab();
2125 0 : SCTAB nLastScTab = aAbs2.Tab();
2126 0 : ScRange aRange(aAbs1.Col(), aAbs1.Row(), 0, aAbs2.Col(), aAbs2.Row(), 0);
2127 0 : for (SCTAB nScTab = nFirstScTab; nScTab <= nLastScTab; ++nScTab)
2128 : {
2129 0 : if( rTabInfo.IsExternalTab( nScTab ) )
2130 : {
2131 0 : aRange.aStart.SetTab( nScTab );
2132 0 : aRange.aEnd.SetTab( nScTab );
2133 0 : maSBBuffer.StoreCellRange( aRange );
2134 : }
2135 : }
2136 : }
2137 0 : }
2138 :
2139 0 : void XclExpLinkManagerImpl8::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2140 : {
2141 0 : maSBBuffer.StoreCell(nFileId, rTabName, rPos);
2142 0 : }
2143 :
2144 0 : void XclExpLinkManagerImpl8::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2145 : {
2146 0 : maSBBuffer.StoreCellRange(nFileId, rTabName, rRange);
2147 0 : }
2148 :
2149 0 : bool XclExpLinkManagerImpl8::InsertAddIn(
2150 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2151 : {
2152 : sal_uInt16 nSupbook;
2153 0 : if( maSBBuffer.InsertAddIn( nSupbook, rnExtName, rName ) )
2154 : {
2155 0 : rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2156 0 : return true;
2157 : }
2158 0 : return false;
2159 : }
2160 :
2161 0 : bool XclExpLinkManagerImpl8::InsertEuroTool(
2162 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2163 : {
2164 : sal_uInt16 nSupbook;
2165 0 : if( maSBBuffer.InsertEuroTool( nSupbook, rnExtName, rName ) )
2166 : {
2167 0 : rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2168 0 : return true;
2169 : }
2170 0 : return false;
2171 : }
2172 :
2173 :
2174 0 : bool XclExpLinkManagerImpl8::InsertDde(
2175 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2176 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2177 : {
2178 : sal_uInt16 nSupbook;
2179 0 : if( maSBBuffer.InsertDde( nSupbook, rnExtName, rApplic, rTopic, rItem ) )
2180 : {
2181 0 : rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2182 0 : return true;
2183 : }
2184 0 : return false;
2185 : }
2186 :
2187 0 : bool XclExpLinkManagerImpl8::InsertExtName( sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2188 : const OUString& rName, const OUString& rUrl, const ScExternalRefCache::TokenArrayRef pArray )
2189 : {
2190 : sal_uInt16 nSupbook;
2191 0 : if( maSBBuffer.InsertExtName( nSupbook, rnExtName, rUrl, rName, pArray ) )
2192 : {
2193 0 : rnExtSheet = InsertXti( XclExpXti( nSupbook, EXC_TAB_EXTERNAL, EXC_TAB_EXTERNAL ) );
2194 0 : return true;
2195 : }
2196 0 : return false;
2197 : }
2198 :
2199 0 : void XclExpLinkManagerImpl8::Save( XclExpStream& rStrm )
2200 : {
2201 0 : if( !maXtiVec.empty() )
2202 : {
2203 : // SUPBOOKs, XCTs, CRNs, EXTERNNAMEs
2204 0 : maSBBuffer.Save( rStrm );
2205 :
2206 : // EXTERNSHEET
2207 0 : sal_uInt16 nCount = ulimit_cast< sal_uInt16 >( maXtiVec.size() );
2208 0 : rStrm.StartRecord( EXC_ID_EXTERNSHEET, 2 + 6 * nCount );
2209 0 : rStrm << nCount;
2210 0 : rStrm.SetSliceSize( 6 );
2211 0 : for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2212 0 : aIt->Save( rStrm );
2213 0 : rStrm.EndRecord();
2214 : }
2215 0 : }
2216 :
2217 0 : sal_uInt16 XclExpLinkManagerImpl8::InsertXti( const XclExpXti& rXti )
2218 : {
2219 0 : for( XclExpXtiVec::const_iterator aIt = maXtiVec.begin(), aEnd = maXtiVec.end(); aIt != aEnd; ++aIt )
2220 0 : if( *aIt == rXti )
2221 0 : return ulimit_cast< sal_uInt16 >( aIt - maXtiVec.begin() );
2222 0 : maXtiVec.push_back( rXti );
2223 0 : return ulimit_cast< sal_uInt16 >( maXtiVec.size() - 1 );
2224 : }
2225 :
2226 0 : XclExpLinkManager::XclExpLinkManager( const XclExpRoot& rRoot ) :
2227 0 : XclExpRoot( rRoot )
2228 : {
2229 0 : switch( GetBiff() )
2230 : {
2231 : case EXC_BIFF5:
2232 0 : mxImpl.reset( new XclExpLinkManagerImpl5( rRoot ) );
2233 0 : break;
2234 : case EXC_BIFF8:
2235 0 : mxImpl.reset( new XclExpLinkManagerImpl8( rRoot ) );
2236 0 : break;
2237 : default:
2238 : DBG_ERROR_BIFF();
2239 : }
2240 0 : }
2241 :
2242 0 : XclExpLinkManager::~XclExpLinkManager()
2243 : {
2244 0 : }
2245 :
2246 0 : void XclExpLinkManager::FindExtSheet(
2247 : sal_uInt16& rnExtSheet, sal_uInt16& rnXclTab,
2248 : SCTAB nScTab, XclExpRefLogEntry* pRefLogEntry )
2249 : {
2250 0 : mxImpl->FindExtSheet( rnExtSheet, rnXclTab, rnXclTab, nScTab, nScTab, pRefLogEntry );
2251 0 : }
2252 :
2253 0 : void XclExpLinkManager::FindExtSheet(
2254 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstXclTab, sal_uInt16& rnLastXclTab,
2255 : SCTAB nFirstScTab, SCTAB nLastScTab, XclExpRefLogEntry* pRefLogEntry )
2256 : {
2257 0 : mxImpl->FindExtSheet( rnExtSheet, rnFirstXclTab, rnLastXclTab, nFirstScTab, nLastScTab, pRefLogEntry );
2258 0 : }
2259 :
2260 0 : sal_uInt16 XclExpLinkManager::FindExtSheet( sal_Unicode cCode )
2261 : {
2262 0 : return mxImpl->FindExtSheet( cCode );
2263 : }
2264 :
2265 0 : void XclExpLinkManager::FindExtSheet( sal_uInt16 nFileId, const OUString& rTabName, sal_uInt16 nXclTabSpan,
2266 : sal_uInt16& rnExtSheet, sal_uInt16& rnFirstSBTab, sal_uInt16& rnLastSBTab,
2267 : XclExpRefLogEntry* pRefLogEntry )
2268 : {
2269 0 : mxImpl->FindExtSheet( nFileId, rTabName, nXclTabSpan, rnExtSheet, rnFirstSBTab, rnLastSBTab, pRefLogEntry );
2270 0 : }
2271 :
2272 0 : void XclExpLinkManager::StoreCell( const ScSingleRefData& rRef, const ScAddress& rPos )
2273 : {
2274 0 : mxImpl->StoreCellRange(rRef, rRef, rPos);
2275 0 : }
2276 :
2277 0 : void XclExpLinkManager::StoreCellRange( const ScComplexRefData& rRef, const ScAddress& rPos )
2278 : {
2279 0 : mxImpl->StoreCellRange(rRef.Ref1, rRef.Ref2, rPos);
2280 0 : }
2281 :
2282 0 : void XclExpLinkManager::StoreCell( sal_uInt16 nFileId, const OUString& rTabName, const ScAddress& rPos )
2283 : {
2284 0 : mxImpl->StoreCell(nFileId, rTabName, rPos);
2285 0 : }
2286 :
2287 0 : void XclExpLinkManager::StoreCellRange( sal_uInt16 nFileId, const OUString& rTabName, const ScRange& rRange )
2288 : {
2289 0 : mxImpl->StoreCellRange(nFileId, rTabName, rRange);
2290 0 : }
2291 :
2292 0 : bool XclExpLinkManager::InsertAddIn(
2293 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2294 : {
2295 0 : return mxImpl->InsertAddIn( rnExtSheet, rnExtName, rName );
2296 : }
2297 :
2298 0 : bool XclExpLinkManager::InsertEuroTool(
2299 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName )
2300 : {
2301 0 : return mxImpl->InsertEuroTool( rnExtSheet, rnExtName, rName );
2302 : }
2303 :
2304 0 : bool XclExpLinkManager::InsertDde(
2305 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName,
2306 : const OUString& rApplic, const OUString& rTopic, const OUString& rItem )
2307 : {
2308 0 : return mxImpl->InsertDde( rnExtSheet, rnExtName, rApplic, rTopic, rItem );
2309 : }
2310 :
2311 0 : bool XclExpLinkManager::InsertExtName(
2312 : sal_uInt16& rnExtSheet, sal_uInt16& rnExtName, const OUString& rName, const OUString& rUrl,
2313 : const ScExternalRefCache::TokenArrayRef pArray )
2314 : {
2315 0 : return mxImpl->InsertExtName( rnExtSheet, rnExtName, rUrl, rName, pArray );
2316 : }
2317 :
2318 0 : void XclExpLinkManager::Save( XclExpStream& rStrm )
2319 : {
2320 0 : mxImpl->Save( rStrm );
2321 0 : }
2322 :
2323 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|