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