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 <config_features.h>
21 :
22 : #include "docsh.hxx"
23 :
24 : #include "scitems.hxx"
25 : #include <editeng/justifyitem.hxx>
26 : #include <comphelper/classids.hxx>
27 : #include <vcl/msgbox.hxx>
28 : #include <vcl/virdev.hxx>
29 : #include <vcl/waitobj.hxx>
30 : #include <svl/PasswordHelper.hxx>
31 : #include <sfx2/app.hxx>
32 : #include <sfx2/bindings.hxx>
33 : #include <sfx2/dinfdlg.hxx>
34 : #include <sfx2/docfile.hxx>
35 : #include <sfx2/fcontnr.hxx>
36 : #include <sfx2/objface.hxx>
37 : #include <sfx2/viewfrm.hxx>
38 : #include <svl/documentlockfile.hxx>
39 : #include <svl/sharecontrolfile.hxx>
40 : #include <svl/urihelper.hxx>
41 : #include "chgtrack.hxx"
42 : #include "chgviset.hxx"
43 : #include <com/sun/star/awt/Key.hpp>
44 : #include <com/sun/star/awt/KeyModifier.hpp>
45 : #include <com/sun/star/container/XContentEnumerationAccess.hpp>
46 : #include <com/sun/star/document/UpdateDocMode.hpp>
47 : #include <com/sun/star/script/vba/VBAEventId.hpp>
48 : #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
49 : #include <com/sun/star/sheet/XSpreadsheetView.hpp>
50 : #include <com/sun/star/task/XJob.hpp>
51 : #include <com/sun/star/ui/theModuleUIConfigurationManagerSupplier.hpp>
52 : #include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
53 : #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
54 : #include <com/sun/star/sheet/XSpreadsheet.hpp>
55 : #include <com/sun/star/container/XIndexAccess.hpp>
56 : #include <com/sun/star/table/XTableChartsSupplier.hpp>
57 : #include <com/sun/star/table/XTableCharts.hpp>
58 : #include <com/sun/star/table/XTableChart.hpp>
59 : #include <com/sun/star/chart2/XChartDocument.hpp>
60 : #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
61 : #include <com/sun/star/frame/XStorable2.hpp>
62 : #include <com/sun/star/frame/Desktop.hpp>
63 :
64 : #include "scabstdlg.hxx"
65 : #include <sot/formats.hxx>
66 :
67 : #include "formulacell.hxx"
68 : #include "postit.hxx"
69 : #include "global.hxx"
70 : #include "filter.hxx"
71 : #include "scmod.hxx"
72 : #include "tabvwsh.hxx"
73 : #include "docfunc.hxx"
74 : #include "imoptdlg.hxx"
75 : #include "impex.hxx"
76 : #include "scresid.hxx"
77 : #include "sc.hrc"
78 : #include "globstr.hrc"
79 : #include "scerrors.hxx"
80 : #include "brdcst.hxx"
81 : #include "stlpool.hxx"
82 : #include "autostyl.hxx"
83 : #include "attrib.hxx"
84 : #include "asciiopt.hxx"
85 : #include "waitoff.hxx"
86 : #include "docpool.hxx"
87 : #include "progress.hxx"
88 : #include "pntlock.hxx"
89 : #include "docuno.hxx"
90 : #include "appoptio.hxx"
91 : #include "detdata.hxx"
92 : #include "printfun.hxx"
93 : #include "dociter.hxx"
94 : #include "cellform.hxx"
95 : #include "chartlis.hxx"
96 : #include "hints.hxx"
97 : #include "xmlwrap.hxx"
98 : #include "drwlayer.hxx"
99 : #include "refreshtimer.hxx"
100 : #include "dbdata.hxx"
101 : #include "scextopt.hxx"
102 : #include "compiler.hxx"
103 : #include "cfgids.hxx"
104 : #include "warnpassword.hxx"
105 : #include "optsolver.hxx"
106 : #include "sheetdata.hxx"
107 : #include "tabprotection.hxx"
108 : #include "docparam.hxx"
109 : #include "docshimp.hxx"
110 : #include "sizedev.hxx"
111 : #include "refreshtimerprotector.hxx"
112 :
113 : #include <officecfg/Office/Calc.hxx>
114 : #include <comphelper/processfactory.hxx>
115 : #include <comphelper/string.hxx>
116 : #include <unotools/configmgr.hxx>
117 : #include "uiitems.hxx"
118 : #include "cellsuno.hxx"
119 : #include "dpobject.hxx"
120 : #include "markdata.hxx"
121 : #include "orcusfilters.hxx"
122 : #include <datastream.hxx>
123 : #include <documentlinkmgr.hxx>
124 : #include <refupdatecontext.hxx>
125 :
126 : #include <config_telepathy.h>
127 :
128 : #if ENABLE_TELEPATHY
129 : #include "sccollaboration.hxx"
130 : #endif
131 :
132 : #include <vector>
133 : #include <boost/shared_ptr.hpp>
134 :
135 : using namespace com::sun::star;
136 : using ::com::sun::star::uno::Reference;
137 : using ::com::sun::star::uno::UNO_QUERY;
138 : using ::com::sun::star::lang::XMultiServiceFactory;
139 : using ::boost::shared_ptr;
140 : using ::std::vector;
141 :
142 : // STATIC DATA -----------------------------------------------------------
143 :
144 : // Filter names (like in sclib.cxx)
145 :
146 : static const sal_Char pFilterSc50[] = "StarCalc 5.0";
147 : static const sal_Char pFilterSc40[] = "StarCalc 4.0";
148 : static const sal_Char pFilterSc30[] = "StarCalc 3.0";
149 : static const sal_Char pFilterSc10[] = "StarCalc 1.0";
150 : static const sal_Char pFilterXML[] = "StarOffice XML (Calc)";
151 : static const sal_Char pFilterAscii[] = "Text - txt - csv (StarCalc)";
152 : static const sal_Char pFilterLotus[] = "Lotus";
153 : static const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
154 : static const sal_Char pFilterExcel4[] = "MS Excel 4.0";
155 : static const sal_Char pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
156 : static const sal_Char pFilterExcel5[] = "MS Excel 5.0/95";
157 : static const sal_Char pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
158 : static const sal_Char pFilterExcel95[] = "MS Excel 95";
159 : static const sal_Char pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
160 : static const sal_Char pFilterExcel97[] = "MS Excel 97";
161 : static const sal_Char pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
162 : static const sal_Char pFilterDBase[] = "dBase";
163 : static const sal_Char pFilterDif[] = "DIF";
164 : static const sal_Char pFilterSylk[] = "SYLK";
165 : static const sal_Char pFilterHtml[] = "HTML (StarCalc)";
166 : static const sal_Char pFilterHtmlWebQ[] = "calc_HTML_WebQuery";
167 : static const sal_Char pFilterRtf[] = "Rich Text Format (StarCalc)";
168 :
169 : #define ScDocShell
170 : #include "scslots.hxx"
171 :
172 27214 : SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell, ScResId(SCSTR_DOCSHELL))
173 :
174 76 : void ScDocShell::InitInterface_Impl()
175 : {
176 76 : }
177 :
178 : // GlobalName of the current version:
179 229707 : SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "scalc" )
180 :
181 24258 : TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: No TypeInfo?
182 :
183 750 : void ScDocShell::FillClass( SvGlobalName* pClassName,
184 : sal_uInt32* pFormat,
185 : OUString* /* pAppName */,
186 : OUString* pFullTypeName,
187 : OUString* pShortTypeName,
188 : sal_Int32 nFileFormat,
189 : bool bTemplate /* = false */) const
190 : {
191 750 : if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
192 : {
193 0 : *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
194 0 : *pFormat = SOT_FORMATSTR_ID_STARCALC_60;
195 0 : *pFullTypeName = OUString( ScResId( SCSTR_LONG_SCDOC_NAME ) );
196 0 : *pShortTypeName = OUString( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
197 : }
198 750 : else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
199 : {
200 750 : *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
201 750 : *pFormat = bTemplate ? SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : SOT_FORMATSTR_ID_STARCALC_8;
202 750 : *pFullTypeName = "calc8";
203 750 : *pShortTypeName = ScResId(SCSTR_SHORT_SCDOC_NAME).toString();
204 : }
205 : else
206 : {
207 : OSL_FAIL("Which version?");
208 : }
209 750 : }
210 :
211 0 : std::vector<Color> ScDocShell::GetDocColors()
212 : {
213 0 : return aDocument.GetDocColors();
214 : }
215 :
216 4 : void ScDocShell::DoEnterHandler()
217 : {
218 4 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
219 4 : if (pViewSh)
220 4 : if (pViewSh->GetViewData().GetDocShell() == this)
221 4 : SC_MOD()->InputEnterHandler();
222 4 : }
223 :
224 0 : SCTAB ScDocShell::GetSaveTab()
225 : {
226 0 : SCTAB nTab = 0;
227 0 : ScTabViewShell* pSh = GetBestViewShell();
228 0 : if (pSh)
229 : {
230 0 : const ScMarkData& rMark = pSh->GetViewData().GetMarkData();
231 0 : nTab = rMark.GetFirstSelected();
232 : }
233 0 : return nTab;
234 : }
235 :
236 0 : sal_uInt16 ScDocShell::GetHiddenInformationState( sal_uInt16 nStates )
237 : {
238 : // get global state like HIDDENINFORMATION_DOCUMENTVERSIONS
239 0 : sal_uInt16 nState = SfxObjectShell::GetHiddenInformationState( nStates );
240 :
241 0 : if ( nStates & HIDDENINFORMATION_RECORDEDCHANGES )
242 : {
243 0 : if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
244 0 : nState |= HIDDENINFORMATION_RECORDEDCHANGES;
245 : }
246 0 : if ( nStates & HIDDENINFORMATION_NOTES )
247 : {
248 0 : SCTAB nTableCount = aDocument.GetTableCount();
249 0 : bool bFound = false;
250 0 : for (SCTAB nTab = 0; nTab < nTableCount && !bFound; ++nTab)
251 : {
252 0 : if (aDocument.HasTabNotes(nTab)) //TODO:
253 0 : bFound = true;
254 : }
255 :
256 0 : if (bFound)
257 0 : nState |= HIDDENINFORMATION_NOTES;
258 : }
259 :
260 0 : return nState;
261 : }
262 :
263 326 : void ScDocShell::BeforeXMLLoading()
264 : {
265 326 : aDocument.EnableIdle(false);
266 :
267 : // prevent unnecessary broadcasts and updates
268 : OSL_ENSURE(pModificator == NULL, "The Modificator should not exist");
269 326 : pModificator = new ScDocShellModificator( *this );
270 :
271 326 : aDocument.SetImportingXML( true );
272 326 : aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
273 326 : aDocument.EnableUndo( false );
274 : // prevent unnecessary broadcasts and "half way listeners"
275 326 : aDocument.SetInsertingFromOtherDoc( true );
276 326 : }
277 :
278 326 : void ScDocShell::AfterXMLLoading(bool bRet)
279 : {
280 326 : if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
281 : {
282 326 : UpdateLinks();
283 : // don't prevent establishing of listeners anymore
284 326 : aDocument.SetInsertingFromOtherDoc( false );
285 326 : if ( bRet )
286 : {
287 326 : ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
288 326 : if (pChartListener)
289 326 : pChartListener->UpdateDirtyCharts();
290 :
291 : // #95582#; set the table names of linked tables to the new path
292 326 : SCTAB nTabCount = aDocument.GetTableCount();
293 908 : for (SCTAB i = 0; i < nTabCount; ++i)
294 : {
295 582 : if (aDocument.IsLinked( i ))
296 : {
297 0 : OUString aName;
298 0 : aDocument.GetName(i, aName);
299 0 : OUString aLinkTabName = aDocument.GetLinkTab(i);
300 0 : sal_Int32 nLinkTabNameLength = aLinkTabName.getLength();
301 0 : sal_Int32 nNameLength = aName.getLength();
302 0 : if (nLinkTabNameLength < nNameLength)
303 : {
304 :
305 : // remove the quottes on begin and end of the docname and restore the escaped quotes
306 0 : const sal_Unicode* pNameBuffer = aName.getStr();
307 0 : if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
308 0 : ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
309 : {
310 0 : OUStringBuffer aDocURLBuffer;
311 0 : bool bQuote = true; // Document name is always quoted
312 0 : ++pNameBuffer;
313 0 : while ( bQuote && *pNameBuffer )
314 : {
315 0 : if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
316 0 : bQuote = false;
317 0 : else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
318 0 : aDocURLBuffer.append(*pNameBuffer); // If escaped quote: only quote in the name
319 0 : ++pNameBuffer;
320 : }
321 :
322 0 : if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
323 : {
324 0 : sal_Int32 nIndex = nNameLength - nLinkTabNameLength;
325 0 : INetURLObject aINetURLObject(aDocURLBuffer.makeStringAndClear());
326 0 : if(aName.match( aLinkTabName, nIndex) &&
327 0 : (aName[nIndex - 1] == '#') && // before the table name should be the # char
328 0 : !aINetURLObject.HasError()) // the docname should be a valid URL
329 : {
330 0 : aName = ScGlobal::GetDocTabName( aDocument.GetLinkDoc( i ), aDocument.GetLinkTab( i ) );
331 0 : aDocument.RenameTab(i, aName, true, true);
332 0 : }
333 : // else; nothing has to happen, because it is a user given name
334 0 : }
335 : // else; nothing has to happen, because it is a user given name
336 : }
337 : // else; nothing has to happen, because it is a user given name
338 0 : }
339 : // else; nothing has to happen, because it is a user given name
340 : }
341 : }
342 :
343 : // #i94570# DataPilot table names have to be unique, or the tables can't be accessed by API.
344 : // If no name (or an invalid name, skipped in ScXMLDataPilotTableContext::EndElement) was set, create a new name.
345 326 : ScDPCollection* pDPCollection = aDocument.GetDPCollection();
346 326 : if ( pDPCollection )
347 : {
348 326 : size_t nDPCount = pDPCollection->GetCount();
349 340 : for (size_t nDP=0; nDP<nDPCount; ++nDP)
350 : {
351 14 : ScDPObject* pDPObj = (*pDPCollection)[nDP];
352 14 : if (pDPObj->GetName().isEmpty())
353 0 : pDPObj->SetName( pDPCollection->CreateNewName() );
354 : }
355 : }
356 : }
357 : }
358 : else
359 0 : aDocument.SetInsertingFromOtherDoc( false );
360 :
361 326 : aDocument.SetImportingXML( false );
362 326 : aDocument.EnableExecuteLink( true );
363 326 : aDocument.EnableUndo( true );
364 326 : bIsEmpty = false;
365 :
366 326 : if (pModificator)
367 : {
368 326 : bool bRecalcState = aDocument.GetHardRecalcState();
369 : //temporarily set hard-recalc to prevent calling ScFormulaCell::Notify()
370 : //which will set the cells dirty.
371 326 : aDocument.SetHardRecalcState(true);
372 326 : delete pModificator;
373 326 : aDocument.SetHardRecalcState(bRecalcState);
374 326 : pModificator = NULL;
375 : }
376 : else
377 : {
378 : OSL_FAIL("The Modificator should exist");
379 : }
380 :
381 326 : aDocument.EnableIdle(true);
382 326 : }
383 :
384 : namespace {
385 :
386 : class LoadMediumGuard
387 : {
388 : public:
389 710 : explicit LoadMediumGuard(ScDocument* pDoc) :
390 710 : mpDoc(pDoc)
391 : {
392 710 : mpDoc->SetLoadingMedium(true);
393 710 : }
394 :
395 710 : ~LoadMediumGuard()
396 : {
397 710 : mpDoc->SetLoadingMedium(false);
398 710 : }
399 : private:
400 : ScDocument* mpDoc;
401 : };
402 :
403 266 : void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData )
404 : {
405 266 : if (!rData.mpDataStream)
406 532 : return;
407 :
408 0 : const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream;
409 0 : if (!r.maRange.IsValid())
410 0 : return;
411 :
412 : // Break the streamed range into the top range and the height limit. A
413 : // height limit of 0 means unlimited i.e. the streamed data will go all
414 : // the way to the last row.
415 :
416 0 : ScRange aTopRange = r.maRange;
417 0 : aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
418 0 : sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1;
419 0 : if (r.maRange.aEnd.Row() == MAXROW)
420 : // Unlimited range.
421 0 : nLimit = 0;
422 :
423 : sc::DataStream::MoveType eMove =
424 0 : r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ?
425 0 : sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN;
426 :
427 0 : sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove, 0);
428 0 : pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty);
429 0 : sc::DocumentLinkManager& rMgr = rShell.GetDocument().GetDocLinkManager();
430 0 : rMgr.setDataStream(pStrm);
431 : }
432 :
433 : }
434 :
435 266 : bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
436 : {
437 266 : LoadMediumGuard aLoadGuard(&aDocument);
438 :
439 : // MacroCallMode is no longer needed, state is kept in SfxObjectShell now
440 :
441 : // no Seek(0) here - always loading from storage, GetInStream must not be called
442 :
443 266 : BeforeXMLLoading();
444 :
445 532 : ScXMLImportWrapper aImport(*this, pLoadMedium, xStor);
446 :
447 266 : bool bRet = false;
448 266 : ErrCode nError = ERRCODE_NONE;
449 266 : aDocument.EnableAdjustHeight(false);
450 266 : if (GetCreateMode() == SFX_CREATE_MODE_ORGANIZER)
451 0 : bRet = aImport.Import(ScXMLImportWrapper::STYLES, nError);
452 : else
453 266 : bRet = aImport.Import(ScXMLImportWrapper::ALL, nError);
454 :
455 266 : if ( nError )
456 0 : pLoadMedium->SetError( nError, OUString( OSL_LOG_PREFIX ) );
457 :
458 266 : processDataStream(*this, aImport.GetImportPostProcessData());
459 :
460 : //if the document was not generated by LibreOffice, do hard recalc in case some other document
461 : //generator saved cached formula results that differ from LibreOffice's calculated results or
462 : //did not use cached formula results.
463 532 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), uno::UNO_QUERY_THROW);
464 532 : uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
465 :
466 532 : Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
467 : ScRecalcOptions nRecalcMode =
468 266 : static_cast<ScRecalcOptions>(officecfg::Office::Calc::Formula::Load::ODFRecalcMode::get(xContext));
469 :
470 266 : bool bHardRecalc = false;
471 266 : if (nRecalcMode == RECALC_ASK)
472 : {
473 0 : OUString sProductName(utl::ConfigManager::getProductName());
474 0 : if (aDocument.IsUserInteractionEnabled() && xDocProps->getGenerator().indexOf(sProductName) == -1)
475 : {
476 : // Generator is not LibreOffice. Ask if the user wants to perform
477 : // full re-calculation.
478 : QueryBox aBox(
479 : GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
480 0 : ScGlobal::GetRscString(STR_QUERY_FORMULA_RECALC_ONLOAD_ODS));
481 0 : aBox.SetCheckBoxText(ScGlobal::GetRscString(STR_ALWAYS_PERFORM_SELECTED));
482 :
483 0 : bHardRecalc = aBox.Execute() == RET_YES;
484 :
485 0 : if (aBox.GetCheckBoxState())
486 : {
487 : // Always perform selected action in the future.
488 0 : boost::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() );
489 0 : officecfg::Office::Calc::Formula::Load::ODFRecalcMode::set(sal_Int32(0), batch);
490 0 : ScFormulaOptions aOpt = SC_MOD()->GetFormulaOptions();
491 0 : aOpt.SetODFRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER);
492 : /* XXX is this really supposed to set the ScModule options?
493 : * Not the ScDocShell options? */
494 0 : SC_MOD()->SetFormulaOptions(aOpt);
495 :
496 0 : batch->commit();
497 0 : }
498 0 : }
499 : }
500 266 : else if (nRecalcMode == RECALC_ALWAYS)
501 0 : bHardRecalc = true;
502 :
503 266 : if (bHardRecalc)
504 0 : DoHardRecalc(false);
505 : else
506 : {
507 : // still need to recalc volatile formula cells.
508 266 : aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
509 : }
510 :
511 266 : AfterXMLLoading(bRet);
512 :
513 266 : aDocument.EnableAdjustHeight(true);
514 532 : return bRet;
515 : }
516 :
517 48 : bool ScDocShell::SaveXML( SfxMedium* pSaveMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
518 : {
519 48 : aDocument.EnableIdle(false);
520 :
521 48 : ScXMLImportWrapper aImport(*this, pSaveMedium, xStor);
522 48 : bool bRet(false);
523 48 : if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
524 48 : bRet = aImport.Export(false);
525 : else
526 0 : bRet = aImport.Export(true);
527 :
528 48 : aDocument.EnableIdle(true);
529 :
530 48 : return bRet;
531 : }
532 :
533 0 : bool ScDocShell::SaveCurrentChart( SfxMedium& rMedium )
534 : {
535 0 : bool bRet = false;
536 :
537 : try
538 : {
539 :
540 0 : uno::Reference< lang::XComponent > xCurrentComponent = frame::Desktop::create( comphelper::getProcessComponentContext() )->getCurrentComponent();
541 :
542 0 : uno::Reference< frame::XStorable2 > xStorable( xCurrentComponent, uno::UNO_QUERY_THROW );
543 :
544 0 : uno::Reference< frame::XModel > xChartDoc ( xCurrentComponent, uno::UNO_QUERY_THROW );
545 :
546 0 : ScXMLChartExportWrapper aExport( xChartDoc, rMedium );
547 0 : bRet = aExport.Export();
548 : }
549 0 : catch(...)
550 : {
551 : SAL_WARN("sc", "exception thrown while saving chart. Bug!!!");
552 : }
553 0 : return bRet;
554 : }
555 :
556 266 : bool ScDocShell::Load( SfxMedium& rMedium )
557 : {
558 266 : LoadMediumGuard aLoadGuard(&aDocument);
559 532 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
560 :
561 : // only the latin script language is loaded
562 : // -> initialize the others from options (before loading)
563 266 : InitOptions(true);
564 :
565 266 : GetUndoManager()->Clear();
566 :
567 266 : bool bRet = SfxObjectShell::Load( rMedium );
568 266 : if( bRet )
569 : {
570 266 : if (GetMedium())
571 : {
572 266 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
573 266 : nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
574 : }
575 :
576 : {
577 : // prepare a valid document for XML filter
578 : // (for ConvertFrom, InitNew is called before)
579 266 : aDocument.MakeTable(0);
580 266 : aDocument.GetStyleSheetPool()->CreateStandardStyles();
581 266 : aDocument.UpdStlShtPtrsFrmNms();
582 :
583 266 : bRet = LoadXML( &rMedium, NULL );
584 : }
585 : }
586 :
587 266 : if (!bRet && !rMedium.GetError())
588 0 : rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, OUString( OSL_LOG_PREFIX ) );
589 :
590 266 : if (rMedium.GetError())
591 0 : SetError( rMedium.GetError(), OUString( OSL_LOG_PREFIX ) );
592 :
593 266 : InitItems();
594 266 : CalcOutputFactor();
595 :
596 : // invalidate eventually temporary table areas
597 266 : if ( bRet )
598 266 : aDocument.InvalidateTableArea();
599 :
600 266 : bIsEmpty = false;
601 266 : FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
602 532 : return bRet;
603 : }
604 :
605 113062 : void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
606 : {
607 113062 : const ScTablesHint* pScHint = dynamic_cast< const ScTablesHint* >( &rHint );
608 113062 : if (pScHint)
609 : {
610 272 : if (pScHint->GetId() == SC_TAB_INSERTED)
611 : {
612 230 : uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor();
613 230 : if ( xVbaEvents.is() ) try
614 : {
615 0 : uno::Sequence< uno::Any > aArgs( 1 );
616 0 : aArgs[0] <<= pScHint->GetTab1();
617 0 : xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs );
618 : }
619 0 : catch( uno::Exception& )
620 : {
621 230 : }
622 : }
623 : }
624 :
625 113062 : if ( dynamic_cast<const SfxSimpleHint*>(&rHint) ) // Without parameter
626 : {
627 40120 : sal_uLong nSlot = static_cast<const SfxSimpleHint&>(rHint).GetId();
628 40120 : switch ( nSlot )
629 : {
630 : case SFX_HINT_TITLECHANGED:
631 2168 : aDocument.SetName( SfxShell::GetName() );
632 : // RegisterNewTargetNames gibts nicht mehr
633 2168 : SfxGetpApp()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
634 2168 : break;
635 40120 : }
636 : }
637 72942 : else if ( dynamic_cast<const SfxStyleSheetHint*>(&rHint) ) // Template changed
638 19550 : NotifyStyle( static_cast<const SfxStyleSheetHint&>(rHint) );
639 53392 : else if ( dynamic_cast<const ScAutoStyleHint*>(&rHint) )
640 : {
641 : //! direct call for AutoStyles
642 :
643 : // this is called synchronously from ScInterpreter::ScStyle,
644 : // modifying the document must be asynchronous
645 : // (handled by AddInitial)
646 :
647 0 : const ScAutoStyleHint& rStlHint = static_cast<const ScAutoStyleHint&>(rHint);
648 0 : ScRange aRange = rStlHint.GetRange();
649 0 : OUString aName1 = rStlHint.GetStyle1();
650 0 : OUString aName2 = rStlHint.GetStyle2();
651 0 : sal_uInt32 nTimeout = rStlHint.GetTimeout();
652 :
653 0 : if (!pAutoStyleList)
654 0 : pAutoStyleList = new ScAutoStyleList(this);
655 0 : pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 );
656 : }
657 53392 : else if ( dynamic_cast<const SfxEventHint*>(&rHint) )
658 : {
659 5120 : sal_uLong nEventId = static_cast<const SfxEventHint*>(&rHint)->GetEventId();
660 5120 : switch ( nEventId )
661 : {
662 : case SFX_EVENT_LOADFINISHED:
663 : {
664 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
665 : // the readonly documents should not be opened in shared mode
666 574 : if ( HasSharedXMLFlagSet() && !SC_MOD()->IsInSharedDocLoading() && !IsReadOnly() )
667 : {
668 0 : if ( SwitchToShared( true, false ) )
669 : {
670 0 : ScViewData* pViewData = GetViewData();
671 0 : ScTabView* pTabView = ( pViewData ? dynamic_cast< ScTabView* >( pViewData->GetView() ) : NULL );
672 0 : if ( pTabView )
673 : {
674 0 : pTabView->UpdateLayerLocks();
675 : }
676 : }
677 : else
678 : {
679 : // switching to shared mode has failed, the document should be opened readonly
680 : // TODO/LATER: And error message should be shown here probably
681 0 : SetReadOnlyUI( true );
682 : }
683 : }
684 : #endif
685 : }
686 574 : break;
687 : case SFX_EVENT_VIEWCREATED:
688 : {
689 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
690 562 : if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() )
691 : {
692 0 : ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
693 0 : if ( aAppOptions.GetShowSharedDocumentWarning() )
694 : {
695 : WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
696 0 : ScGlobal::GetRscString( STR_SHARED_DOC_WARNING ) );
697 0 : aBox.SetDefaultCheckBoxText();
698 0 : aBox.Execute();
699 0 : bool bChecked = aBox.GetCheckBoxState();
700 0 : if ( bChecked )
701 : {
702 0 : aAppOptions.SetShowSharedDocumentWarning( !bChecked );
703 0 : SC_MOD()->SetAppOptions( aAppOptions );
704 0 : }
705 0 : }
706 : }
707 : #endif
708 : try
709 : {
710 : uno::Reference< uno::XComponentContext > xContext(
711 562 : comphelper::getProcessComponentContext() );
712 : uno::Reference< lang::XMultiServiceFactory > xServiceManager(
713 562 : xContext->getServiceManager(),
714 1124 : uno::UNO_QUERY_THROW );
715 1124 : uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xServiceManager, uno::UNO_QUERY_THROW );
716 562 : uno::Reference< container::XEnumeration> xEnum = xEnumAccess->createContentEnumeration(
717 1124 : OUString( "com.sun.star.sheet.SpreadsheetDocumentJob" ) );
718 562 : if ( xEnum.is() )
719 : {
720 1124 : while ( xEnum->hasMoreElements() )
721 : {
722 0 : uno::Any aAny = xEnum->nextElement();
723 0 : uno::Reference< lang::XSingleComponentFactory > xFactory;
724 0 : aAny >>= xFactory;
725 0 : if ( xFactory.is() )
726 : {
727 0 : uno::Reference< task::XJob > xJob( xFactory->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
728 0 : uno::Sequence< beans::NamedValue > aArgsForJob(1);
729 0 : ScViewData* pViewData = GetViewData();
730 0 : SfxViewShell* pViewShell = ( pViewData ? pViewData->GetViewShell() : NULL );
731 0 : SfxViewFrame* pViewFrame = ( pViewShell ? pViewShell->GetViewFrame() : NULL );
732 0 : SfxFrame* pFrame = ( pViewFrame ? &pViewFrame->GetFrame() : NULL );
733 0 : uno::Reference< frame::XController > xController = ( pFrame ? pFrame->GetController() : 0 );
734 0 : uno::Reference< sheet::XSpreadsheetView > xSpreadsheetView( xController, uno::UNO_QUERY_THROW );
735 0 : aArgsForJob[0] = beans::NamedValue( OUString( "SpreadsheetView" ),
736 0 : uno::makeAny( xSpreadsheetView ) );
737 0 : xJob->execute( aArgsForJob );
738 : }
739 0 : }
740 562 : }
741 : }
742 0 : catch ( uno::Exception & )
743 : {
744 : }
745 : }
746 562 : break;
747 : case SFX_EVENT_SAVEDOC:
748 : {
749 : #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
750 0 : if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
751 : {
752 0 : bool bSuccess = false;
753 0 : bool bRetry = true;
754 0 : while ( bRetry )
755 : {
756 0 : bRetry = false;
757 0 : uno::Reference< frame::XModel > xModel;
758 : try
759 : {
760 : // load shared file
761 0 : xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
762 0 : uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
763 :
764 : // check if shared flag is set in shared file
765 0 : bool bShared = false;
766 0 : ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
767 0 : ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : NULL );
768 0 : if ( pSharedDocShell )
769 : {
770 0 : bShared = pSharedDocShell->HasSharedXMLFlagSet();
771 : }
772 :
773 : // #i87870# check if shared status was disabled and enabled again
774 0 : bool bOwnEntry = false;
775 0 : bool bEntriesNotAccessible = false;
776 : try
777 : {
778 0 : ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
779 0 : bOwnEntry = aControlFile.HasOwnEntry();
780 : }
781 0 : catch ( uno::Exception& )
782 : {
783 0 : bEntriesNotAccessible = true;
784 : }
785 :
786 0 : if ( bShared && bOwnEntry )
787 : {
788 0 : uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
789 :
790 0 : if ( xStorable->isReadonly() )
791 : {
792 0 : xCloseable->close( sal_True );
793 :
794 0 : OUString aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
795 0 : bool bNoLockAccess = false;
796 : try
797 : {
798 0 : ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
799 0 : uno::Sequence< OUString > aData = aLockFile.GetLockData();
800 0 : if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
801 : {
802 0 : if ( !aData[LOCKFILE_OOOUSERNAME_ID].isEmpty() )
803 : {
804 0 : aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
805 : }
806 0 : else if ( !aData[LOCKFILE_SYSUSERNAME_ID].isEmpty() )
807 : {
808 0 : aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
809 : }
810 0 : }
811 : }
812 0 : catch ( uno::Exception& )
813 : {
814 0 : bNoLockAccess = true;
815 : }
816 :
817 0 : if ( bNoLockAccess )
818 : {
819 : // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
820 0 : ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
821 : }
822 : else
823 : {
824 0 : OUString aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
825 0 : aMessage = aMessage.replaceFirst( "%1", aUserName );
826 :
827 0 : WarningBox aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
828 0 : if ( aBox.Execute() == RET_RETRY )
829 : {
830 0 : bRetry = true;
831 0 : }
832 0 : }
833 : }
834 : else
835 : {
836 : // merge changes from shared file into temp file
837 0 : bool bSaveToShared = false;
838 0 : if ( pSharedDocShell )
839 : {
840 0 : bSaveToShared = MergeSharedDocument( pSharedDocShell );
841 : }
842 :
843 : // close shared file
844 0 : xCloseable->close( sal_True );
845 :
846 : // TODO: keep file lock on shared file
847 :
848 : // store to shared file
849 0 : if ( bSaveToShared )
850 : {
851 0 : bool bChangedViewSettings = false;
852 0 : ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
853 0 : if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
854 : {
855 0 : pChangeViewSet->SetShowChanges( false );
856 0 : pChangeViewSet->SetShowAccepted( false );
857 0 : aDocument.SetChangeViewSettings( *pChangeViewSet );
858 0 : bChangedViewSettings = true;
859 : }
860 :
861 0 : uno::Reference< frame::XStorable > xStor( GetModel(), uno::UNO_QUERY_THROW );
862 : // TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
863 0 : uno::Sequence< beans::PropertyValue > aValues(1);
864 0 : aValues[0].Name = "FilterName";
865 0 : aValues[0].Value <<= OUString( GetMedium()->GetFilter()->GetFilterName() );
866 :
867 0 : SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, false);
868 0 : if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
869 : {
870 0 : aValues.realloc( 2 );
871 0 : aValues[1].Name = "Password";
872 0 : aValues[1].Value <<= pPasswordItem->GetValue();
873 : }
874 :
875 0 : SC_MOD()->SetInSharedDocSaving( true );
876 0 : xStor->storeToURL( GetSharedFileURL(), aValues );
877 0 : SC_MOD()->SetInSharedDocSaving( false );
878 :
879 0 : if ( bChangedViewSettings )
880 : {
881 0 : pChangeViewSet->SetShowChanges( true );
882 0 : pChangeViewSet->SetShowAccepted( true );
883 0 : aDocument.SetChangeViewSettings( *pChangeViewSet );
884 0 : }
885 : }
886 :
887 0 : bSuccess = true;
888 0 : GetUndoManager()->Clear();
889 0 : }
890 : }
891 : else
892 : {
893 0 : xCloseable->close( sal_True );
894 :
895 0 : if ( bEntriesNotAccessible )
896 : {
897 : // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
898 0 : ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
899 : }
900 : else
901 : {
902 : WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
903 0 : ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
904 0 : aBox.Execute();
905 :
906 0 : SfxBindings* pBindings = GetViewBindings();
907 0 : if ( pBindings )
908 : {
909 0 : pBindings->ExecuteSynchron( SID_SAVEASDOC );
910 0 : }
911 : }
912 0 : }
913 : }
914 0 : catch ( uno::Exception& )
915 : {
916 : OSL_FAIL( "SFX_EVENT_SAVEDOC: caught exception\n" );
917 0 : SC_MOD()->SetInSharedDocSaving( false );
918 :
919 : try
920 : {
921 0 : uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
922 0 : xClose->close( sal_True );
923 : }
924 0 : catch ( uno::Exception& )
925 : {
926 : }
927 : }
928 0 : }
929 :
930 0 : if ( !bSuccess )
931 0 : SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
932 : }
933 : #endif
934 :
935 0 : if (pSheetSaveData)
936 0 : pSheetSaveData->SetInSupportedSave(true);
937 : }
938 0 : break;
939 : case SFX_EVENT_SAVEASDOC:
940 : {
941 4 : if ( GetDocument().GetExternalRefManager()->containsUnsavedReferences() )
942 : {
943 : WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
944 0 : ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
945 :
946 0 : if( RET_NO == aBox.Execute())
947 : {
948 0 : SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
949 0 : }
950 : }
951 : } // fall through
952 : case SFX_EVENT_SAVETODOC:
953 : // #i108978# If no event is sent before saving, there will also be no "...DONE" event,
954 : // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
955 : // if there is a SAVE/SAVEAS/SAVETO event first.
956 30 : if (pSheetSaveData)
957 24 : pSheetSaveData->SetInSupportedSave(true);
958 30 : break;
959 : case SFX_EVENT_SAVEDOCDONE:
960 : case SFX_EVENT_SAVEASDOCDONE:
961 : {
962 : // new positions are used after "save" and "save as", but not "save to"
963 4 : UseSheetSaveEntries(); // use positions from saved file for next saving
964 : } // fall through
965 : case SFX_EVENT_SAVETODOCDONE:
966 : // only reset the flag, don't use the new positions
967 30 : if (pSheetSaveData)
968 26 : pSheetSaveData->SetInSupportedSave(false);
969 30 : break;
970 : default:
971 : {
972 : }
973 3924 : break;
974 : }
975 : }
976 113062 : }
977 :
978 : // Load contents for organizer
979 0 : bool ScDocShell::LoadFrom( SfxMedium& rMedium )
980 : {
981 0 : LoadMediumGuard aLoadGuard(&aDocument);
982 0 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
983 :
984 0 : WaitObject aWait( GetActiveDialogParent() );
985 :
986 0 : bool bRet = false;
987 :
988 0 : if (GetMedium())
989 : {
990 0 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
991 0 : nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
992 : }
993 :
994 : // until loading/saving only the styles in XML is implemented,
995 : // load the whole file
996 0 : bRet = LoadXML( &rMedium, NULL );
997 0 : InitItems();
998 :
999 0 : SfxObjectShell::LoadFrom( rMedium );
1000 :
1001 0 : return bRet;
1002 : }
1003 :
1004 0 : static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert)
1005 : {
1006 0 : OUStringBuffer aBuf;
1007 0 : std::vector< OUString > aTokens;
1008 0 : sal_Int32 n = rOption.getLength();
1009 0 : const sal_Unicode* p = rOption.getStr();
1010 0 : for (sal_Int32 i = 0; i < n; ++i)
1011 : {
1012 0 : const sal_Unicode c = p[i];
1013 0 : if (c == ' ')
1014 : {
1015 0 : if (!aBuf.isEmpty())
1016 0 : aTokens.push_back( aBuf.makeStringAndClear() );
1017 : }
1018 : else
1019 0 : aBuf.append(c);
1020 : }
1021 :
1022 0 : if (!aBuf.isEmpty())
1023 0 : aTokens.push_back( aBuf.makeStringAndClear() );
1024 :
1025 0 : rLang = LanguageType( 0 );
1026 0 : rDateConvert = false;
1027 :
1028 0 : if (aTokens.size() > 0)
1029 0 : rLang = static_cast<LanguageType>(aTokens[0].toInt32());
1030 0 : if (aTokens.size() > 1)
1031 0 : rDateConvert = static_cast<bool>(aTokens[1].toInt32());
1032 0 : }
1033 :
1034 178 : bool ScDocShell::ConvertFrom( SfxMedium& rMedium )
1035 : {
1036 178 : LoadMediumGuard aLoadGuard(&aDocument);
1037 :
1038 178 : bool bRet = false; // sal_False means user quit!
1039 : // On error: Set error at stream
1040 :
1041 356 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1042 :
1043 178 : GetUndoManager()->Clear();
1044 :
1045 : // Set optimal col width after import?
1046 178 : bool bSetColWidths = false;
1047 178 : bool bSetSimpleTextColWidths = false;
1048 178 : ScColWidthParam aColWidthParam[MAXCOLCOUNT];
1049 178 : ScRange aColWidthRange;
1050 : // Set optimal row height after import?
1051 178 : bool bSetRowHeights = false;
1052 :
1053 356 : vector<ScDocRowHeightUpdater::TabRanges> aRecalcRowRangesArray;
1054 :
1055 : // All filters need the complete file in one piece (not asynchronously)
1056 : // So make sure that we transfer the whole file with CreateFileStream
1057 178 : rMedium.GetPhysicalName(); //! Call CreateFileStream directly, if available
1058 :
1059 178 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
1060 178 : nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
1061 :
1062 178 : const SfxFilter* pFilter = rMedium.GetFilter();
1063 178 : if (pFilter)
1064 : {
1065 178 : OUString aFltName = pFilter->GetFilterName();
1066 :
1067 178 : bool bCalc3 = ( aFltName.equalsAscii(pFilterSc30) );
1068 178 : bool bCalc4 = ( aFltName.equalsAscii(pFilterSc40) );
1069 178 : if (!bCalc3 && !bCalc4)
1070 178 : aDocument.SetInsertingFromOtherDoc( true );
1071 :
1072 178 : if (aFltName.equalsAscii(pFilterXML))
1073 0 : bRet = LoadXML( &rMedium, NULL );
1074 178 : else if (aFltName.equalsAscii(pFilterSc10))
1075 : {
1076 0 : SvStream* pStream = rMedium.GetInStream();
1077 0 : if (pStream)
1078 : {
1079 0 : FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
1080 0 : if (eError != eERR_OK)
1081 : {
1082 0 : if (!GetError())
1083 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1084 : }
1085 : else
1086 0 : bRet = true;
1087 : }
1088 : }
1089 178 : else if (aFltName.equalsAscii(pFilterLotus))
1090 : {
1091 8 : OUString sItStr;
1092 8 : SfxItemSet* pSet = rMedium.GetItemSet();
1093 : const SfxPoolItem* pItem;
1094 16 : if ( pSet && SfxItemState::SET ==
1095 8 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1096 : {
1097 0 : sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1098 : }
1099 :
1100 8 : if (sItStr.isEmpty())
1101 : {
1102 : // default for lotus import (from API without options):
1103 : // IBM_437 encoding
1104 8 : sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
1105 : }
1106 :
1107 8 : FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
1108 8 : ScGlobal::GetCharsetValue(sItStr));
1109 8 : if (eError != eERR_OK)
1110 : {
1111 2 : if (!GetError())
1112 2 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1113 :
1114 2 : if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1115 0 : bRet = true;
1116 : }
1117 : else
1118 6 : bRet = true;
1119 8 : bSetColWidths = true;
1120 8 : bSetRowHeights = true;
1121 : }
1122 680 : else if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterExcel5) ||
1123 366 : aFltName.equalsAscii(pFilterExcel95) || aFltName.equalsAscii(pFilterExcel97) ||
1124 78 : aFltName.equalsAscii(pFilterEx4Temp) || aFltName.equalsAscii(pFilterEx5Temp) ||
1125 222 : aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp) )
1126 : {
1127 146 : EXCIMPFORMAT eFormat = EIF_AUTO;
1128 146 : if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterEx4Temp) )
1129 0 : eFormat = EIF_BIFF_LE4;
1130 584 : else if ( aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
1131 438 : aFltName.equalsAscii(pFilterEx5Temp) || aFltName.equalsAscii(pFilterEx95Temp) )
1132 0 : eFormat = EIF_BIFF5;
1133 146 : else if ( aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx97Temp) )
1134 146 : eFormat = EIF_BIFF8;
1135 :
1136 146 : MakeDrawLayer(); //! In the filter
1137 146 : CalcOutputFactor(); // prepare update of row height
1138 146 : FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
1139 146 : aDocument.UpdateFontCharSet();
1140 146 : if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
1141 146 : aDocument.UpdateChartListenerCollection(); //! For all imports?
1142 :
1143 : // all graphics objects must have names
1144 146 : aDocument.EnsureGraphicNames();
1145 :
1146 146 : if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
1147 : {
1148 0 : if (!GetError())
1149 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1150 0 : bRet = true;
1151 : }
1152 146 : else if (eError != eERR_OK)
1153 : {
1154 4 : if (!GetError())
1155 4 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1156 : }
1157 : else
1158 142 : bRet = true;
1159 : }
1160 24 : else if (aFltName.equalsAscii(pFilterAscii))
1161 : {
1162 4 : SfxItemSet* pSet = rMedium.GetItemSet();
1163 : const SfxPoolItem* pItem;
1164 4 : ScAsciiOptions aOptions;
1165 4 : bool bOptInit = false;
1166 :
1167 8 : if ( pSet && SfxItemState::SET ==
1168 4 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1169 : {
1170 0 : aOptions.ReadFromString( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1171 0 : bOptInit = true;
1172 : }
1173 :
1174 4 : if ( !bOptInit )
1175 : {
1176 : // default for ascii import (from API without options):
1177 : // ISO8859-1/MS_1252 encoding, comma, double quotes
1178 :
1179 4 : aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1180 4 : aOptions.SetFieldSeps( OUString(',') );
1181 4 : aOptions.SetTextSep( '"' );
1182 : }
1183 :
1184 4 : FltError eError = eERR_OK;
1185 : bool bOverflowRow, bOverflowCol, bOverflowCell;
1186 4 : bOverflowRow = bOverflowCol = bOverflowCell = false;
1187 :
1188 4 : if( ! rMedium.IsStorage() )
1189 : {
1190 4 : ScImportExport aImpEx( &aDocument );
1191 4 : aImpEx.SetExtOptions( aOptions );
1192 :
1193 4 : SvStream* pInStream = rMedium.GetInStream();
1194 4 : if (pInStream)
1195 : {
1196 4 : pInStream->SetStreamCharSet( aOptions.GetCharSet() );
1197 4 : pInStream->Seek( 0 );
1198 4 : bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
1199 4 : eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
1200 4 : aDocument.StartAllListeners();
1201 4 : sc::SetFormulaDirtyContext aCxt;
1202 4 : aDocument.SetAllFormulasDirty(aCxt);
1203 4 : INetURLObject aURLObjForDefaultNameSheetName(rMedium.GetName());
1204 4 : aDocument.RenameTab(0,aURLObjForDefaultNameSheetName.GetBase());
1205 4 : bOverflowRow = aImpEx.IsOverflowRow();
1206 4 : bOverflowCol = aImpEx.IsOverflowCol();
1207 4 : bOverflowCell = aImpEx.IsOverflowCell();
1208 : }
1209 : else
1210 : {
1211 : OSL_FAIL( "No Stream" );
1212 4 : }
1213 : }
1214 :
1215 4 : if (eError != eERR_OK)
1216 : {
1217 0 : if (!GetError())
1218 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1219 : }
1220 4 : else if (!GetError() && (bOverflowRow || bOverflowCol || bOverflowCell))
1221 : {
1222 : // precedence: row, column, cell
1223 : FltError nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW :
1224 : (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW :
1225 0 : SCWARN_IMPORT_CELL_OVERFLOW));
1226 0 : SetError( nWarn, OUString( OSL_LOG_PREFIX ));
1227 : }
1228 4 : bSetColWidths = true;
1229 4 : bSetSimpleTextColWidths = true;
1230 : }
1231 20 : else if (aFltName.equalsAscii(pFilterDBase))
1232 : {
1233 2 : OUString sItStr;
1234 2 : SfxItemSet* pSet = rMedium.GetItemSet();
1235 : const SfxPoolItem* pItem;
1236 4 : if ( pSet && SfxItemState::SET ==
1237 2 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1238 : {
1239 0 : sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1240 : }
1241 :
1242 2 : if (sItStr.isEmpty())
1243 : {
1244 : // default for dBase import (from API without options):
1245 : // IBM_850 encoding
1246 :
1247 2 : sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
1248 : }
1249 :
1250 4 : ScDocRowHeightUpdater::TabRanges aRecalcRanges(0);
1251 2 : sal_uLong eError = DBaseImport( rMedium.GetPhysicalName(),
1252 4 : ScGlobal::GetCharsetValue(sItStr), aColWidthParam, *aRecalcRanges.mpRanges );
1253 2 : aRecalcRowRangesArray.push_back(aRecalcRanges);
1254 :
1255 2 : if (eError != eERR_OK)
1256 : {
1257 0 : if (!GetError())
1258 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1259 0 : bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
1260 : }
1261 : else
1262 2 : bRet = true;
1263 :
1264 2 : aColWidthRange.aStart.SetRow( 1 ); // Except for the column header
1265 2 : bSetColWidths = true;
1266 4 : bSetSimpleTextColWidths = true;
1267 : }
1268 18 : else if (aFltName.equalsAscii(pFilterDif))
1269 : {
1270 2 : SvStream* pStream = rMedium.GetInStream();
1271 2 : if (pStream)
1272 : {
1273 : FltError eError;
1274 2 : OUString sItStr;
1275 2 : SfxItemSet* pSet = rMedium.GetItemSet();
1276 : const SfxPoolItem* pItem;
1277 4 : if ( pSet && SfxItemState::SET ==
1278 2 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1279 : {
1280 0 : sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1281 : }
1282 :
1283 2 : if (sItStr.isEmpty())
1284 : {
1285 : // default for DIF import (from API without options):
1286 : // ISO8859-1/MS_1252 encoding
1287 :
1288 2 : sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
1289 : }
1290 :
1291 2 : eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
1292 2 : ScGlobal::GetCharsetValue(sItStr));
1293 2 : if (eError != eERR_OK)
1294 : {
1295 0 : if (!GetError())
1296 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1297 :
1298 0 : if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1299 0 : bRet = true;
1300 : }
1301 : else
1302 2 : bRet = true;
1303 : }
1304 2 : bSetColWidths = true;
1305 2 : bSetSimpleTextColWidths = true;
1306 2 : bSetRowHeights = true;
1307 : }
1308 16 : else if (aFltName.equalsAscii(pFilterSylk))
1309 : {
1310 8 : FltError eError = SCERR_IMPORT_UNKNOWN;
1311 8 : if( !rMedium.IsStorage() )
1312 : {
1313 8 : ScImportExport aImpEx( &aDocument );
1314 :
1315 8 : SvStream* pInStream = rMedium.GetInStream();
1316 8 : if (pInStream)
1317 : {
1318 8 : pInStream->Seek( 0 );
1319 8 : bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SOT_FORMATSTR_ID_SYLK );
1320 8 : eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
1321 8 : aDocument.StartAllListeners();
1322 8 : sc::SetFormulaDirtyContext aCxt;
1323 8 : aDocument.SetAllFormulasDirty(aCxt);
1324 : }
1325 : else
1326 : {
1327 : OSL_FAIL( "No Stream" );
1328 8 : }
1329 : }
1330 :
1331 8 : if ( eError != eERR_OK && !GetError() )
1332 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1333 8 : bSetColWidths = true;
1334 8 : bSetSimpleTextColWidths = true;
1335 8 : bSetRowHeights = true;
1336 : }
1337 8 : else if (aFltName.equalsAscii(pFilterQPro6))
1338 : {
1339 6 : FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
1340 6 : if (eError != eERR_OK)
1341 : {
1342 2 : if (!GetError())
1343 2 : SetError( eError, OUString( OSL_LOG_PREFIX ) );
1344 2 : if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1345 0 : bRet = true;
1346 : }
1347 : else
1348 4 : bRet = true;
1349 : // TODO: Filter should set column widths. Not doing it here, it may
1350 : // result in very narrow or wide columns, depending on content.
1351 : // Setting row heights makes cells with font size attribution or
1352 : // wrapping enabled look nicer..
1353 6 : bSetRowHeights = true;
1354 : }
1355 2 : else if (aFltName.equalsAscii(pFilterRtf))
1356 : {
1357 0 : FltError eError = SCERR_IMPORT_UNKNOWN;
1358 0 : if( !rMedium.IsStorage() )
1359 : {
1360 0 : SvStream* pInStream = rMedium.GetInStream();
1361 0 : if (pInStream)
1362 : {
1363 0 : pInStream->Seek( 0 );
1364 0 : ScRange aRange;
1365 0 : eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
1366 0 : if (eError != eERR_OK)
1367 : {
1368 0 : if (!GetError())
1369 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1370 :
1371 0 : if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1372 0 : bRet = true;
1373 : }
1374 : else
1375 0 : bRet = true;
1376 0 : aDocument.StartAllListeners();
1377 0 : sc::SetFormulaDirtyContext aCxt;
1378 0 : aDocument.SetAllFormulasDirty(aCxt);
1379 0 : bSetColWidths = true;
1380 0 : bSetRowHeights = true;
1381 : }
1382 : else
1383 : {
1384 : OSL_FAIL( "No Stream" );
1385 : }
1386 : }
1387 :
1388 0 : if ( eError != eERR_OK && !GetError() )
1389 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1390 : }
1391 2 : else if (aFltName.equalsAscii(pFilterHtml) || aFltName.equalsAscii(pFilterHtmlWebQ))
1392 : {
1393 2 : FltError eError = SCERR_IMPORT_UNKNOWN;
1394 2 : bool bWebQuery = aFltName.equalsAscii(pFilterHtmlWebQ);
1395 2 : if( !rMedium.IsStorage() )
1396 : {
1397 2 : SvStream* pInStream = rMedium.GetInStream();
1398 2 : if (pInStream)
1399 : {
1400 2 : LanguageType eLang = LANGUAGE_SYSTEM;
1401 2 : bool bDateConvert = false;
1402 2 : SfxItemSet* pSet = rMedium.GetItemSet();
1403 : const SfxPoolItem* pItem;
1404 4 : if ( pSet && SfxItemState::SET ==
1405 2 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1406 : {
1407 0 : OUString aFilterOption = (static_cast<const SfxStringItem*>(pItem))->GetValue();
1408 0 : lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert);
1409 : }
1410 :
1411 2 : pInStream->Seek( 0 );
1412 2 : ScRange aRange;
1413 : // HTML does its own ColWidth/RowHeight
1414 2 : CalcOutputFactor();
1415 2 : SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eLang);
1416 2 : eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
1417 2 : GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert );
1418 2 : if (eError != eERR_OK)
1419 : {
1420 0 : if (!GetError())
1421 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1422 :
1423 0 : if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1424 0 : bRet = true;
1425 : }
1426 : else
1427 2 : bRet = true;
1428 2 : aDocument.StartAllListeners();
1429 :
1430 2 : sc::SetFormulaDirtyContext aCxt;
1431 2 : aDocument.SetAllFormulasDirty(aCxt);
1432 : }
1433 : else
1434 : {
1435 : OSL_FAIL( "No Stream" );
1436 : }
1437 : }
1438 :
1439 2 : if ( eError != eERR_OK && !GetError() )
1440 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
1441 : }
1442 : else
1443 : {
1444 0 : if (!GetError())
1445 0 : SetError(SCERR_IMPORT_NI, OUString( OSL_LOG_PREFIX ));
1446 : }
1447 :
1448 178 : if (!bCalc3)
1449 178 : aDocument.SetInsertingFromOtherDoc( false );
1450 : }
1451 : else
1452 : {
1453 : OSL_FAIL("No Filter in ConvertFrom");
1454 : }
1455 :
1456 178 : InitItems();
1457 178 : CalcOutputFactor();
1458 178 : if ( bRet && (bSetColWidths || bSetRowHeights) )
1459 : { // Adjust column width/row height; base 100% zoom
1460 26 : Fraction aZoom( 1, 1 );
1461 26 : double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom / GetOutputFactor(); // Factor is printer display ratio
1462 26 : double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
1463 26 : VirtualDevice aVirtDev;
1464 : // all sheets (for Excel import)
1465 26 : SCTAB nTabCount = aDocument.GetTableCount();
1466 52 : for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1467 : {
1468 : SCCOL nEndCol;
1469 : SCROW nEndRow;
1470 26 : aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1471 26 : aColWidthRange.aEnd.SetCol( nEndCol );
1472 26 : aColWidthRange.aEnd.SetRow( nEndRow );
1473 26 : ScMarkData aMark;
1474 26 : aMark.SetMarkArea( aColWidthRange );
1475 26 : aMark.MarkToMulti();
1476 :
1477 : // Order is important: First width, then height
1478 26 : if ( bSetColWidths )
1479 : {
1480 202 : for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
1481 : {
1482 180 : if (!bSetSimpleTextColWidths)
1483 32 : aColWidthParam[nCol].mbSimpleText = false;
1484 :
1485 : sal_uInt16 nWidth = aDocument.GetOptimalColWidth(
1486 : nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoom, aZoom, false, &aMark,
1487 180 : &aColWidthParam[nCol] );
1488 : aDocument.SetColWidth( nCol, nTab,
1489 180 : nWidth + (sal_uInt16)ScGlobal::nLastColWidthExtra );
1490 : }
1491 : }
1492 26 : }
1493 :
1494 26 : if (bSetRowHeights)
1495 : {
1496 : // Update all rows in all tables.
1497 20 : ScSizeDeviceProvider aProv(this);
1498 20 : ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), NULL);
1499 20 : aUpdater.update();
1500 : }
1501 6 : else if (!aRecalcRowRangesArray.empty())
1502 : {
1503 : // Update only specified row ranges for better performance.
1504 2 : ScSizeDeviceProvider aProv(this);
1505 2 : ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &aRecalcRowRangesArray);
1506 2 : aUpdater.update();
1507 26 : }
1508 : }
1509 178 : FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
1510 :
1511 : // invalidate eventually temporary table areas
1512 178 : if ( bRet )
1513 170 : aDocument.InvalidateTableArea();
1514 :
1515 178 : bIsEmpty = false;
1516 :
1517 356 : return bRet;
1518 : }
1519 :
1520 0 : bool ScDocShell::LoadExternal( SfxMedium& rMed )
1521 : {
1522 0 : const SfxFilter* pFilter = rMed.GetFilter();
1523 0 : if (!pFilter)
1524 0 : return false;
1525 :
1526 0 : if (pFilter->GetProviderName() == "orcus")
1527 : {
1528 0 : ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
1529 0 : if (!pOrcus)
1530 0 : return false;
1531 :
1532 0 : const OUString& rFilterName = pFilter->GetName();
1533 0 : if (rFilterName == "gnumeric")
1534 : {
1535 0 : if (!pOrcus->importGnumeric(aDocument, rMed))
1536 0 : return false;
1537 : }
1538 0 : else if (rFilterName == "csv")
1539 : {
1540 0 : if (!pOrcus->importCSV(aDocument, rMed))
1541 0 : return false;
1542 : }
1543 0 : else if (rFilterName == "xlsx")
1544 : {
1545 0 : if (!pOrcus->importXLSX(aDocument, rMed))
1546 0 : return false;
1547 : }
1548 0 : else if (rFilterName == "ods")
1549 : {
1550 0 : if (!pOrcus->importODS(aDocument, rMed))
1551 0 : return false;
1552 : }
1553 :
1554 0 : FinishedLoading(SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES);
1555 0 : return true;
1556 : }
1557 :
1558 0 : return false;
1559 : }
1560 :
1561 48 : ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
1562 48 : : mrDocShell( rDocShell)
1563 : {
1564 : // DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
1565 :
1566 48 : ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
1567 48 : if (pCharts)
1568 48 : pCharts->UpdateDirtyCharts(); // Charts to be updated.
1569 48 : mrDocShell.aDocument.StopTemporaryChartLock();
1570 48 : if (mrDocShell.pAutoStyleList)
1571 0 : mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
1572 48 : if (mrDocShell.aDocument.HasExternalRefManager())
1573 : {
1574 14 : ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1575 14 : if (pRefMgr && pRefMgr->hasExternalData())
1576 : {
1577 0 : pRefMgr->setAllCacheTableReferencedStati( false);
1578 0 : mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
1579 : }
1580 : }
1581 48 : if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD)
1582 14 : mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
1583 48 : }
1584 :
1585 48 : ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
1586 : {
1587 48 : if (mrDocShell.aDocument.HasExternalRefManager())
1588 : {
1589 48 : ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1590 48 : if (pRefMgr && pRefMgr->hasExternalData())
1591 : {
1592 : // Prevent accidental data loss due to lack of knowledge.
1593 0 : pRefMgr->setAllCacheTableReferencedStati( true);
1594 : }
1595 : }
1596 48 : }
1597 :
1598 0 : bool ScDocShell::Save()
1599 : {
1600 0 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1601 :
1602 0 : PrepareSaveGuard aPrepareGuard( *this);
1603 :
1604 0 : SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst( this );
1605 0 : if (pFrame1)
1606 : {
1607 0 : vcl::Window* pWindow = &pFrame1->GetWindow();
1608 0 : if ( pWindow )
1609 : {
1610 0 : vcl::Window* pSysWin = pWindow->GetSystemWindow();
1611 0 : if ( pSysWin )
1612 : {
1613 0 : pSysWin->SetAccessibleName(OUString());
1614 : }
1615 : }
1616 : }
1617 : // wait cursor is handled with progress bar
1618 0 : bool bRet = SfxObjectShell::Save();
1619 0 : if( bRet )
1620 0 : bRet = SaveXML( GetMedium(), NULL );
1621 0 : return bRet;
1622 : }
1623 :
1624 : namespace {
1625 :
1626 : /**
1627 : * Remove the file name from the full path, to keep only the directory path.
1628 : */
1629 86 : void popFileName(OUString& rPath)
1630 : {
1631 86 : if (!rPath.isEmpty())
1632 : {
1633 76 : INetURLObject aURLObj(rPath);
1634 76 : aURLObj.removeSegment();
1635 76 : rPath = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
1636 : }
1637 86 : }
1638 :
1639 : }
1640 :
1641 48 : bool ScDocShell::SaveAs( SfxMedium& rMedium )
1642 : {
1643 48 : OUString aCurPath; // empty for new document that hasn't been saved.
1644 48 : const SfxMedium* pCurMedium = GetMedium();
1645 48 : if (pCurMedium)
1646 : {
1647 48 : aCurPath = pCurMedium->GetName();
1648 48 : popFileName(aCurPath);
1649 : }
1650 :
1651 48 : if (!aCurPath.isEmpty())
1652 : {
1653 : // current document has a path -> not a brand-new document.
1654 38 : OUString aNewPath = rMedium.GetName();
1655 38 : popFileName(aNewPath);
1656 76 : OUString aRel = URIHelper::simpleNormalizedMakeRelative(aCurPath, aNewPath);
1657 38 : if (!aRel.isEmpty())
1658 : {
1659 : // Directory path will change before and after the save.
1660 34 : aDocument.InvalidateStreamOnSave();
1661 38 : }
1662 : }
1663 :
1664 48 : ScTabViewShell* pViewShell = GetBestViewShell();
1665 48 : bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA1);
1666 48 : if (bNeedsRehash)
1667 : // legacy xls hash double-hashed by SHA1 is also supported.
1668 0 : bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
1669 :
1670 48 : if (pViewShell && bNeedsRehash)
1671 : {
1672 0 : if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1))
1673 : // password re-type cancelled. Don't save the document.
1674 0 : return false;
1675 : }
1676 :
1677 96 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1678 :
1679 96 : PrepareSaveGuard aPrepareGuard( *this);
1680 :
1681 96 : OUString aFltName = rMedium.GetFilter()->GetFilterName();
1682 48 : bool bChartExport = aFltName.indexOf("chart8") != -1;
1683 :
1684 : // wait cursor is handled with progress bar
1685 48 : bool bRet = false;
1686 48 : if(!bChartExport)
1687 : {
1688 48 : bRet = SfxObjectShell::SaveAs( rMedium );
1689 48 : if (bRet)
1690 48 : bRet = SaveXML( &rMedium, NULL );
1691 : }
1692 : else
1693 : {
1694 0 : bRet = SaveCurrentChart( rMedium );
1695 : }
1696 :
1697 96 : return bRet;
1698 : }
1699 :
1700 0 : bool ScDocShell::IsInformationLost()
1701 : {
1702 : //FIXME: If we have time build a correct own way how to handle this
1703 0 : return SfxObjectShell::IsInformationLost();
1704 : }
1705 :
1706 : namespace {
1707 :
1708 : // Xcl-like column width measured in characters of standard font.
1709 0 : sal_Int32 lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth )
1710 : {
1711 0 : double f = nWidth;
1712 0 : f *= 1328.0 / 25.0;
1713 0 : f += 90.0;
1714 0 : f *= 1.0 / 23.0;
1715 0 : f /= 256.0;
1716 :
1717 0 : return sal_Int32( f );
1718 : }
1719 :
1720 0 : void lcl_ScDocShell_GetFixedWidthString( OUString& rStr, const ScDocument& rDoc,
1721 : SCTAB nTab, SCCOL nCol, bool bValue, SvxCellHorJustify eHorJust )
1722 : {
1723 0 : OUString aString = rStr;
1724 : sal_Int32 nLen = lcl_ScDocShell_GetColWidthInChars(
1725 0 : rDoc.GetColWidth( nCol, nTab ) );
1726 : //If the text won't fit in the column
1727 0 : if ( nLen < aString.getLength() )
1728 : {
1729 0 : OUStringBuffer aReplacement;
1730 0 : if (bValue)
1731 0 : aReplacement.append("###");
1732 : else
1733 0 : aReplacement.append(aString);
1734 : //truncate to the number of characters that should fit, even in the
1735 : //bValue case nLen might be < len ###
1736 0 : aString = comphelper::string::truncateToLength(aReplacement, nLen).makeStringAndClear();
1737 : }
1738 0 : if ( nLen > aString.getLength() )
1739 : {
1740 0 : if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
1741 0 : eHorJust = SVX_HOR_JUSTIFY_RIGHT;
1742 0 : sal_Int32 nBlanks = nLen - aString.getLength();
1743 0 : switch ( eHorJust )
1744 : {
1745 : case SVX_HOR_JUSTIFY_RIGHT:
1746 : {
1747 0 : OUStringBuffer aTmp;
1748 0 : aTmp = comphelper::string::padToLength( aTmp, nBlanks, ' ' );
1749 0 : aString = aTmp.append(aString).makeStringAndClear();
1750 : }
1751 0 : break;
1752 : case SVX_HOR_JUSTIFY_CENTER:
1753 : {
1754 0 : sal_Int32 nLeftPad = nBlanks / 2;
1755 0 : OUStringBuffer aTmp;
1756 0 : comphelper::string::padToLength( aTmp, nLeftPad, ' ' );
1757 0 : aTmp.append(aString);
1758 0 : comphelper::string::padToLength( aTmp, nLen, ' ' );
1759 0 : aString = aTmp.makeStringAndClear();
1760 : }
1761 0 : break;
1762 : default:
1763 : {
1764 0 : OUStringBuffer aTmp(aString);
1765 0 : comphelper::string::padToLength( aTmp, nLen, ' ' );
1766 0 : aString = aTmp.makeStringAndClear();
1767 : }
1768 : }
1769 : }
1770 0 : rStr = aString;
1771 0 : }
1772 :
1773 0 : void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
1774 : const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
1775 : {
1776 0 : OUString aString;
1777 : lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, false,
1778 0 : SVX_HOR_JUSTIFY_STANDARD );
1779 0 : rStream.WriteUnicodeOrByteText( aString );
1780 0 : }
1781 :
1782 : template<typename StrT, typename SepCharT>
1783 0 : sal_Int32 getTextSepPos(
1784 : const StrT& rStr, const ScImportOptions& rAsciiOpt, const SepCharT& rTextSep, const SepCharT& rFieldSep, bool& rNeedQuotes)
1785 : {
1786 : // #i116636# quotes are needed if text delimiter (quote), field delimiter,
1787 : // or LF is in the cell text.
1788 0 : sal_Int32 nPos = rStr.indexOf(rTextSep);
1789 0 : rNeedQuotes = rAsciiOpt.bQuoteAllText || (nPos >= 0) ||
1790 0 : (rStr.indexOf(rFieldSep) >= 0) ||
1791 0 : (rStr.indexOf('\n') >= 0);
1792 0 : return nPos;
1793 : }
1794 :
1795 : template<typename StrT, typename StrBufT>
1796 0 : void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr)
1797 : {
1798 0 : while (nPos >= 0)
1799 : {
1800 0 : StrBufT aBuf(rStr);
1801 0 : aBuf.insert(nPos, rStrDelim);
1802 0 : rStr = aBuf.makeStringAndClear();
1803 0 : nPos = rStr.indexOf(rStrDelim, nPos+1+rStrDelim.getLength());
1804 : }
1805 0 : }
1806 :
1807 : }
1808 :
1809 0 : void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
1810 : {
1811 0 : sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
1812 0 : sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
1813 0 : rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet;
1814 0 : bool bFixedWidth = rAsciiOpt.bFixedWidth;
1815 0 : bool bSaveAsShown = rAsciiOpt.bSaveAsShown;
1816 0 : bool bShowFormulas = rAsciiOpt.bSaveFormulas;
1817 :
1818 0 : rtl_TextEncoding eOldCharSet = rStream.GetStreamCharSet();
1819 0 : rStream.SetStreamCharSet( eCharSet );
1820 0 : sal_uInt16 nOldNumberFormatInt = rStream.GetNumberFormatInt();
1821 0 : OString aStrDelimEncoded; // only used if not Unicode
1822 0 : OUString aStrDelimDecoded; // only used if context encoding
1823 0 : OString aDelimEncoded;
1824 0 : OUString aDelimDecoded;
1825 : bool bContextOrNotAsciiEncoding;
1826 0 : if ( eCharSet == RTL_TEXTENCODING_UNICODE )
1827 : {
1828 0 : rStream.StartWritingUnicodeText();
1829 0 : bContextOrNotAsciiEncoding = false;
1830 : }
1831 : else
1832 : {
1833 0 : aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
1834 0 : aDelimEncoded = OString(&cDelim, 1, eCharSet);
1835 : rtl_TextEncodingInfo aInfo;
1836 0 : aInfo.StructSize = sizeof(aInfo);
1837 0 : if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
1838 : {
1839 : bContextOrNotAsciiEncoding =
1840 0 : (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
1841 0 : ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
1842 0 : if ( bContextOrNotAsciiEncoding )
1843 : {
1844 0 : aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet);
1845 0 : aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet);
1846 : }
1847 : }
1848 : else
1849 0 : bContextOrNotAsciiEncoding = false;
1850 : }
1851 :
1852 0 : SCCOL nStartCol = 0;
1853 0 : SCROW nStartRow = 0;
1854 0 : SCTAB nTab = GetSaveTab();
1855 : SCCOL nEndCol;
1856 : SCROW nEndRow;
1857 0 : aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1858 :
1859 0 : ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
1860 :
1861 0 : OUString aString;
1862 :
1863 0 : bool bTabProtect = aDocument.IsTabProtected( nTab );
1864 :
1865 : SCCOL nCol;
1866 : SCROW nRow;
1867 0 : SCCOL nNextCol = nStartCol;
1868 0 : SCROW nNextRow = nStartRow;
1869 : SCCOL nEmptyCol;
1870 : SCROW nEmptyRow;
1871 0 : SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
1872 :
1873 : ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
1874 0 : nEndCol, nEndRow );
1875 : ScRefCellValue* pCell;
1876 0 : while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
1877 : {
1878 0 : bool bProgress = false; // only upon line change
1879 0 : if ( nNextRow < nRow )
1880 : { // empty rows or/and empty columns up to end of row
1881 0 : bProgress = true;
1882 0 : for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
1883 : { // remaining columns of last row
1884 0 : if ( bFixedWidth )
1885 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1886 0 : aDocument, nTab, nEmptyCol );
1887 0 : else if ( cDelim != 0 )
1888 0 : rStream.WriteUniOrByteChar( cDelim );
1889 : }
1890 0 : endlub( rStream );
1891 0 : nNextRow++;
1892 0 : for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
1893 : { // completely empty rows
1894 0 : for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
1895 : {
1896 0 : if ( bFixedWidth )
1897 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1898 0 : aDocument, nTab, nEmptyCol );
1899 0 : else if ( cDelim != 0 )
1900 0 : rStream.WriteUniOrByteChar( cDelim );
1901 : }
1902 0 : endlub( rStream );
1903 : }
1904 0 : for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
1905 : { // empty columns at beginning of row
1906 0 : if ( bFixedWidth )
1907 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1908 0 : aDocument, nTab, nEmptyCol );
1909 0 : else if ( cDelim != 0 )
1910 0 : rStream.WriteUniOrByteChar( cDelim );
1911 : }
1912 0 : nNextRow = nRow;
1913 : }
1914 0 : else if ( nNextCol < nCol )
1915 : { // empty columns in same row
1916 0 : for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
1917 : { // columns in between
1918 0 : if ( bFixedWidth )
1919 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1920 0 : aDocument, nTab, nEmptyCol );
1921 0 : else if ( cDelim != 0 )
1922 0 : rStream.WriteUniOrByteChar( cDelim );
1923 : }
1924 : }
1925 0 : if ( nCol == nEndCol )
1926 : {
1927 0 : bProgress = true;
1928 0 : nNextCol = nStartCol;
1929 0 : nNextRow = nRow + 1;
1930 : }
1931 : else
1932 0 : nNextCol = nCol + 1;
1933 :
1934 0 : CellType eType = pCell->meType;
1935 0 : ScAddress aPos(nCol, nRow, nTab);
1936 0 : if ( bTabProtect )
1937 : {
1938 : const ScProtectionAttr* pProtAttr =
1939 : static_cast<const ScProtectionAttr*>( aDocument.GetAttr(
1940 0 : nCol, nRow, nTab, ATTR_PROTECTION ));
1941 0 : if ( pProtAttr->GetHideCell() ||
1942 0 : ( eType == CELLTYPE_FORMULA && bShowFormulas &&
1943 0 : pProtAttr->GetHideFormula() ) )
1944 0 : eType = CELLTYPE_NONE; // hide
1945 : }
1946 : bool bString;
1947 0 : switch ( eType )
1948 : {
1949 : case CELLTYPE_NONE:
1950 0 : aString = "";
1951 0 : bString = false;
1952 0 : break;
1953 : case CELLTYPE_FORMULA :
1954 : {
1955 : sal_uInt16 nErrCode;
1956 0 : if ( bShowFormulas )
1957 : {
1958 0 : pCell->mpFormula->GetFormula(aString);
1959 0 : bString = true;
1960 : }
1961 0 : else if ((nErrCode = pCell->mpFormula->GetErrCode()) != 0)
1962 : {
1963 0 : aString = ScGlobal::GetErrorString( nErrCode );
1964 0 : bString = true;
1965 : }
1966 0 : else if (pCell->mpFormula->IsValue())
1967 : {
1968 0 : sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1969 0 : if ( bFixedWidth || bSaveAsShown )
1970 : {
1971 : Color* pDummy;
1972 0 : aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1973 0 : bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
1974 : }
1975 : else
1976 : {
1977 0 : ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
1978 0 : bString = false;
1979 : }
1980 : }
1981 : else
1982 : {
1983 0 : if ( bSaveAsShown )
1984 : {
1985 0 : sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1986 : Color* pDummy;
1987 0 : aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1988 : }
1989 : else
1990 0 : aString = pCell->mpFormula->GetString().getString();
1991 0 : bString = true;
1992 : }
1993 : }
1994 0 : break;
1995 : case CELLTYPE_STRING :
1996 0 : if ( bSaveAsShown )
1997 : {
1998 0 : sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1999 : Color* pDummy;
2000 0 : aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2001 : }
2002 : else
2003 0 : aString = pCell->mpString->getString();
2004 0 : bString = true;
2005 0 : break;
2006 : case CELLTYPE_EDIT :
2007 : {
2008 0 : const EditTextObject* pObj = pCell->mpEditText;
2009 0 : EditEngine& rEngine = aDocument.GetEditEngine();
2010 0 : rEngine.SetText( *pObj);
2011 0 : aString = rEngine.GetText(); // including LF
2012 0 : bString = true;
2013 : }
2014 0 : break;
2015 : case CELLTYPE_VALUE :
2016 : {
2017 : sal_uInt32 nFormat;
2018 0 : aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
2019 0 : if ( bFixedWidth || bSaveAsShown )
2020 : {
2021 : Color* pDummy;
2022 0 : aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2023 0 : bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
2024 : }
2025 : else
2026 : {
2027 0 : ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
2028 0 : bString = false;
2029 : }
2030 : }
2031 0 : break;
2032 : default:
2033 : OSL_FAIL( "ScDocShell::AsciiSave: unknown CellType" );
2034 0 : aString = "";
2035 0 : bString = false;
2036 : }
2037 :
2038 0 : if ( bFixedWidth )
2039 : {
2040 : SvxCellHorJustify eHorJust = (SvxCellHorJustify)
2041 : static_cast<const SvxHorJustifyItem*>( aDocument.GetAttr( nCol, nRow,
2042 0 : nTab, ATTR_HOR_JUSTIFY ))->GetValue();
2043 : lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
2044 0 : !bString, eHorJust );
2045 0 : rStream.WriteUnicodeOrByteText( aString );
2046 : }
2047 : else
2048 : {
2049 0 : OUString aUniString = aString;// TODO: remove that later
2050 0 : if (!bString && cStrDelim != 0 && !aUniString.isEmpty())
2051 : {
2052 0 : sal_Unicode c = aUniString[0];
2053 0 : bString = (c == cStrDelim || c == ' ' ||
2054 0 : aUniString.endsWith(" ") ||
2055 0 : aUniString.indexOf(cStrDelim) >= 0);
2056 0 : if (!bString && cDelim != 0)
2057 0 : bString = (aUniString.indexOf(cDelim) >= 0);
2058 : }
2059 0 : if ( bString )
2060 : {
2061 0 : if ( cStrDelim != 0 ) //@ BugId 55355
2062 : {
2063 0 : if ( eCharSet == RTL_TEXTENCODING_UNICODE )
2064 : {
2065 0 : bool bNeedQuotes = false;
2066 : sal_Int32 nPos = getTextSepPos(
2067 0 : aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes);
2068 :
2069 : escapeTextSep<OUString, OUStringBuffer>(
2070 0 : nPos, OUString(cStrDelim), aUniString);
2071 :
2072 0 : if ( bNeedQuotes )
2073 0 : rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2074 0 : write_uInt16s_FromOUString(rStream, aUniString);
2075 0 : if ( bNeedQuotes )
2076 0 : rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2077 : }
2078 : else
2079 : {
2080 : // This is nasty. The Unicode to byte encoding
2081 : // may convert typographical quotation marks to ASCII
2082 : // quotation marks, which may interfer with the delimiter,
2083 : // so we have to escape delimiters after the string has
2084 : // been encoded. Since this may happen also with UTF-8
2085 : // encoded typographical quotation marks if such was
2086 : // specified as a delimiter we have to check for the full
2087 : // encoded delimiter string, not just one character.
2088 : // Now for RTL_TEXTENCODING_ISO_2022_... and similar brain
2089 : // dead encodings where one code point (and especially a
2090 : // low ASCII value) may represent different characters, we
2091 : // have to convert forth and back and forth again. Same for
2092 : // UTF-7 since it is a context sensitive encoding too.
2093 :
2094 0 : if ( bContextOrNotAsciiEncoding )
2095 : {
2096 : // to byte encoding
2097 0 : OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2098 : // back to Unicode
2099 0 : OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
2100 :
2101 : // search on re-decoded string
2102 0 : bool bNeedQuotes = false;
2103 : sal_Int32 nPos = getTextSepPos(
2104 0 : aStrDec, rAsciiOpt, aStrDelimDecoded, aDelimDecoded, bNeedQuotes);
2105 :
2106 : escapeTextSep<OUString, OUStringBuffer>(
2107 0 : nPos, aStrDelimDecoded, aStrDec);
2108 :
2109 : // write byte re-encoded
2110 0 : if ( bNeedQuotes )
2111 0 : rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2112 0 : rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
2113 0 : if ( bNeedQuotes )
2114 0 : rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2115 : }
2116 : else
2117 : {
2118 0 : OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2119 :
2120 : // search on encoded string
2121 0 : bool bNeedQuotes = false;
2122 : sal_Int32 nPos = getTextSepPos(
2123 0 : aStrEnc, rAsciiOpt, aStrDelimEncoded, aDelimEncoded, bNeedQuotes);
2124 :
2125 : escapeTextSep<OString, OStringBuffer>(
2126 0 : nPos, aStrDelimEncoded, aStrEnc);
2127 :
2128 : // write byte encoded
2129 0 : if ( bNeedQuotes )
2130 : rStream.Write(
2131 0 : aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2132 0 : rStream.Write(aStrEnc.getStr(), aStrEnc.getLength());
2133 0 : if ( bNeedQuotes )
2134 : rStream.Write(
2135 0 : aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2136 : }
2137 : }
2138 : }
2139 : else
2140 0 : rStream.WriteUnicodeOrByteText( aUniString );
2141 : }
2142 : else
2143 0 : rStream.WriteUnicodeOrByteText( aUniString );
2144 : }
2145 :
2146 0 : if( nCol < nEndCol )
2147 : {
2148 0 : if(cDelim!=0) //@ BugId 55355
2149 0 : rStream.WriteUniOrByteChar( cDelim );
2150 : }
2151 : else
2152 0 : endlub( rStream );
2153 :
2154 0 : if ( bProgress )
2155 0 : aProgress.SetStateOnPercent( nRow );
2156 : }
2157 :
2158 : // write out empty if requested
2159 0 : if ( nNextRow <= nEndRow )
2160 : {
2161 0 : for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
2162 : { // remaining empty columns of last row
2163 0 : if ( bFixedWidth )
2164 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2165 0 : aDocument, nTab, nEmptyCol );
2166 0 : else if ( cDelim != 0 )
2167 0 : rStream.WriteUniOrByteChar( cDelim );
2168 : }
2169 0 : endlub( rStream );
2170 0 : nNextRow++;
2171 : }
2172 0 : for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
2173 : { // entire empty rows
2174 0 : for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
2175 : {
2176 0 : if ( bFixedWidth )
2177 : lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2178 0 : aDocument, nTab, nEmptyCol );
2179 0 : else if ( cDelim != 0 )
2180 0 : rStream.WriteUniOrByteChar( cDelim );
2181 : }
2182 0 : endlub( rStream );
2183 : }
2184 :
2185 0 : rStream.SetStreamCharSet( eOldCharSet );
2186 0 : rStream.SetNumberFormatInt( nOldNumberFormatInt );
2187 0 : }
2188 :
2189 32 : bool ScDocShell::ConvertTo( SfxMedium &rMed )
2190 : {
2191 32 : ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
2192 :
2193 : // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
2194 : // it's already in ExecuteSave (as for Save and SaveAs)
2195 :
2196 32 : if (pAutoStyleList)
2197 0 : pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now
2198 32 : if (GetCreateMode()== SFX_CREATE_MODE_STANDARD)
2199 8 : SfxObjectShell::SetVisArea( Rectangle() ); // Edited normally -> no VisArea
2200 :
2201 : OSL_ENSURE( rMed.GetFilter(), "Filter == 0" );
2202 :
2203 32 : bool bRet = false;
2204 64 : OUString aFltName = rMed.GetFilter()->GetFilterName();
2205 :
2206 32 : if (aFltName.equalsAscii(pFilterXML))
2207 : {
2208 : //TODO/LATER: this shouldn't happen!
2209 : OSL_FAIL("XML filter in ConvertFrom?!");
2210 0 : bRet = SaveXML( &rMed, NULL );
2211 : }
2212 128 : else if (aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
2213 44 : aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx5Temp) ||
2214 44 : aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp))
2215 : {
2216 26 : WaitObject aWait( GetActiveDialogParent() );
2217 :
2218 26 : bool bDoSave = true;
2219 26 : if( ScTabViewShell* pViewShell = GetBestViewShell() )
2220 : {
2221 4 : ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
2222 4 : if( !pExtDocOpt )
2223 4 : aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
2224 4 : pViewShell->GetViewData().WriteExtOptions( *pExtDocOpt );
2225 :
2226 : /* #i104990# If the imported document contains a medium
2227 : password, determine if we can save it, otherwise ask the users
2228 : whether they want to save without it. */
2229 4 : if( (rMed.GetFilter()->GetFilterFlags() & SFX_FILTER_ENCRYPTION) == 0 )
2230 : {
2231 0 : SfxItemSet* pItemSet = rMed.GetItemSet();
2232 0 : const SfxPoolItem* pItem = 0;
2233 0 : if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, true, &pItem ) == SfxItemState::SET )
2234 : {
2235 0 : bDoSave = ScWarnPassword::WarningOnPassword( rMed );
2236 : // #i42858# remove password from medium (warn only one time)
2237 0 : if( bDoSave )
2238 0 : pItemSet->ClearItem( SID_PASSWORD );
2239 : }
2240 : }
2241 :
2242 4 : if( bDoSave )
2243 : {
2244 4 : bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
2245 4 : bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
2246 : }
2247 : }
2248 :
2249 26 : if( bDoSave )
2250 : {
2251 26 : ExportFormatExcel eFormat = ExpBiff5;
2252 26 : if( aFltName.equalsAscii( pFilterExcel97 ) || aFltName.equalsAscii( pFilterEx97Temp ) )
2253 26 : eFormat = ExpBiff8;
2254 26 : FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
2255 :
2256 26 : if( eError && !GetError() )
2257 0 : SetError( eError, OUString( OSL_LOG_PREFIX ) );
2258 :
2259 : // don't return false for warnings
2260 26 : bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
2261 : }
2262 : else
2263 : {
2264 : // export aborted, i.e. "Save without password" warning
2265 0 : SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
2266 26 : }
2267 : }
2268 6 : else if (aFltName.equalsAscii(pFilterAscii))
2269 : {
2270 0 : SvStream* pStream = rMed.GetOutStream();
2271 0 : if (pStream)
2272 : {
2273 0 : OUString sItStr;
2274 0 : SfxItemSet* pSet = rMed.GetItemSet();
2275 : const SfxPoolItem* pItem;
2276 0 : if ( pSet && SfxItemState::SET ==
2277 0 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2278 : {
2279 0 : sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
2280 : }
2281 :
2282 0 : if ( sItStr.isEmpty() )
2283 : {
2284 : // default for ascii export (from API without options):
2285 : // ISO8859-1/MS_1252 encoding, comma, double quotes
2286 :
2287 0 : ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
2288 0 : sItStr = aDefOptions.BuildString();
2289 : }
2290 :
2291 0 : WaitObject aWait( GetActiveDialogParent() );
2292 0 : ScImportOptions aOptions( sItStr );
2293 0 : AsciiSave( *pStream, aOptions );
2294 0 : bRet = true;
2295 :
2296 0 : if (aDocument.GetTableCount() > 1)
2297 0 : if (!rMed.GetError())
2298 0 : rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2299 : }
2300 : }
2301 6 : else if (aFltName.equalsAscii(pFilterDBase))
2302 : {
2303 0 : OUString sCharSet;
2304 0 : SfxItemSet* pSet = rMed.GetItemSet();
2305 : const SfxPoolItem* pItem;
2306 0 : if ( pSet && SfxItemState::SET ==
2307 0 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2308 : {
2309 0 : sCharSet = static_cast<const SfxStringItem*>(pItem)->GetValue();
2310 : }
2311 :
2312 0 : if (sCharSet.isEmpty())
2313 : {
2314 : // default for dBase export (from API without options):
2315 : // IBM_850 encoding
2316 :
2317 0 : sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
2318 : }
2319 :
2320 0 : WaitObject aWait( GetActiveDialogParent() );
2321 : // FIXME: Hack so that the Sba opened TempFile can be overwritten
2322 0 : rMed.CloseOutStream();
2323 0 : bool bHasMemo = false;
2324 :
2325 : sal_uLong eError = DBaseExport(
2326 0 : rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo);
2327 :
2328 0 : if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
2329 : {
2330 0 : eError = eERR_OK;
2331 : }
2332 :
2333 0 : INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE );
2334 0 : if ( bHasMemo )
2335 0 : aTmpFile.setExtension(OUString("dbt"));
2336 0 : if ( eError != eERR_OK )
2337 : {
2338 0 : if (!GetError())
2339 0 : SetError(eError, OUString( OSL_LOG_PREFIX ));
2340 0 : if ( bHasMemo && IsDocument( aTmpFile ) )
2341 0 : KillFile( aTmpFile );
2342 : }
2343 : else
2344 : {
2345 0 : bRet = true;
2346 0 : if ( bHasMemo )
2347 : {
2348 : const SfxStringItem* pNameItem =
2349 0 : static_cast<const SfxStringItem*>( rMed.GetItemSet()->GetItem( SID_FILE_NAME ) );
2350 0 : INetURLObject aDbtFile( pNameItem->GetValue(), INET_PROT_FILE );
2351 0 : aDbtFile.setExtension(OUString("dbt"));
2352 0 : if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
2353 0 : bRet = false;
2354 0 : if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
2355 0 : bRet = false;
2356 0 : if ( !bRet )
2357 : {
2358 0 : KillFile( aTmpFile );
2359 0 : if ( !GetError() )
2360 0 : SetError( SCERR_EXPORT_DATA, OUString( OSL_LOG_PREFIX ) );
2361 0 : }
2362 : }
2363 0 : }
2364 : }
2365 6 : else if (aFltName.equalsAscii(pFilterDif))
2366 : {
2367 0 : SvStream* pStream = rMed.GetOutStream();
2368 0 : if (pStream)
2369 : {
2370 0 : OUString sItStr;
2371 0 : SfxItemSet* pSet = rMed.GetItemSet();
2372 : const SfxPoolItem* pItem;
2373 0 : if ( pSet && SfxItemState::SET ==
2374 0 : pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2375 : {
2376 0 : sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
2377 : }
2378 :
2379 0 : if (sItStr.isEmpty())
2380 : {
2381 : // default for DIF export (from API without options):
2382 : // ISO8859-1/MS_1252 encoding
2383 :
2384 0 : sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
2385 : }
2386 :
2387 0 : WaitObject aWait( GetActiveDialogParent() );
2388 0 : ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
2389 0 : ScGlobal::GetCharsetValue(sItStr) );
2390 0 : bRet = true;
2391 :
2392 0 : if (aDocument.GetTableCount() > 1)
2393 0 : if (!rMed.GetError())
2394 0 : rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2395 : }
2396 : }
2397 6 : else if (aFltName.equalsAscii(pFilterSylk))
2398 : {
2399 0 : SvStream* pStream = rMed.GetOutStream();
2400 0 : if ( pStream )
2401 : {
2402 0 : WaitObject aWait( GetActiveDialogParent() );
2403 :
2404 : SCCOL nEndCol;
2405 : SCROW nEndRow;
2406 0 : aDocument.GetCellArea( 0, nEndCol, nEndRow );
2407 0 : ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
2408 :
2409 0 : ScImportExport aImExport( &aDocument, aRange );
2410 0 : aImExport.SetFormulas( true );
2411 0 : bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_SYLK );
2412 : }
2413 : }
2414 6 : else if (aFltName.equalsAscii(pFilterHtml))
2415 : {
2416 6 : SvStream* pStream = rMed.GetOutStream();
2417 6 : if ( pStream )
2418 : {
2419 6 : SfxItemSet* pSet = rMed.GetItemSet();
2420 : const SfxPoolItem* pItem;
2421 6 : OUString sFilterOptions;
2422 :
2423 6 : if (pSet->GetItemState(SID_FILE_FILTEROPTIONS, true, &pItem) == SfxItemState::SET)
2424 4 : sFilterOptions = static_cast<const SfxStringItem*>(pItem)->GetValue();
2425 :
2426 12 : WaitObject aWait(GetActiveDialogParent());
2427 12 : ScImportExport aImExport(&aDocument);
2428 6 : aImExport.SetStreamPath(rMed.GetName());
2429 6 : aImExport.SetFilterOptions(sFilterOptions);
2430 6 : bRet = aImExport.ExportStream(*pStream, rMed.GetBaseURL(true), SOT_FORMATSTR_ID_HTML);
2431 6 : if (bRet && !aImExport.GetNonConvertibleChars().isEmpty())
2432 : {
2433 : SetError(*new StringErrorInfo(
2434 : SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
2435 : aImExport.GetNonConvertibleChars(),
2436 0 : ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO), OUString(OSL_LOG_PREFIX));
2437 6 : }
2438 : }
2439 : }
2440 : else
2441 : {
2442 0 : if (GetError())
2443 0 : SetError(SCERR_IMPORT_NI, OUString(OSL_LOG_PREFIX));
2444 : }
2445 64 : return bRet;
2446 : }
2447 :
2448 32 : bool ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
2449 : {
2450 32 : return SfxObjectShell::SaveCompleted( xStor );
2451 : }
2452 :
2453 38 : bool ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
2454 : {
2455 38 : bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
2456 :
2457 : // SC_HINT_DOC_SAVED for change ReadOnly -> Read/Write
2458 38 : Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
2459 38 : return bRet;
2460 : }
2461 :
2462 0 : bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId )
2463 : {
2464 : // #i112634# ask VBA event handlers whether to save or print the document
2465 :
2466 : using namespace ::com::sun::star::script::vba;
2467 :
2468 0 : sal_Int32 nVbaEventId = VBAEventId::NO_EVENT;
2469 0 : uno::Sequence< uno::Any > aArgs;
2470 0 : switch( nSlotId )
2471 : {
2472 : case SID_SAVEDOC:
2473 : case SID_SAVEASDOC:
2474 0 : nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE;
2475 0 : aArgs.realloc( 1 );
2476 0 : aArgs[ 0 ] <<= (nSlotId == SID_SAVEASDOC);
2477 0 : break;
2478 : case SID_PRINTDOC:
2479 : case SID_PRINTDOCDIRECT:
2480 0 : nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT;
2481 0 : break;
2482 : }
2483 :
2484 0 : bool bSlotExecutable = true;
2485 0 : if( nVbaEventId != VBAEventId::NO_EVENT ) try
2486 : {
2487 0 : uno::Reference< XVBAEventProcessor > xEventProcessor( aDocument.GetVbaEventProcessor(), uno::UNO_QUERY_THROW );
2488 0 : xEventProcessor->processVbaEvent( nVbaEventId, aArgs );
2489 : }
2490 0 : catch( util::VetoException& )
2491 : {
2492 0 : bSlotExecutable = false;
2493 : }
2494 0 : catch( uno::Exception& )
2495 : {
2496 : }
2497 0 : return bSlotExecutable;
2498 : }
2499 :
2500 4 : bool ScDocShell::PrepareClose( bool bUI )
2501 : {
2502 4 : if(SC_MOD()->GetCurRefDlgId()>0)
2503 : {
2504 0 : SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
2505 0 : if( pFrame )
2506 : {
2507 0 : SfxViewShell* p = pFrame->GetViewShell();
2508 0 : ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
2509 0 : if(pViewSh!=NULL)
2510 : {
2511 0 : vcl::Window *pWin=pViewSh->GetWindow();
2512 0 : if(pWin!=NULL) pWin->GrabFocus();
2513 : }
2514 : }
2515 :
2516 0 : return false;
2517 : }
2518 4 : if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
2519 : {
2520 0 : ErrorMessage(STR_CLOSE_ERROR_LINK);
2521 0 : return false;
2522 : }
2523 :
2524 4 : DoEnterHandler();
2525 :
2526 : // start 'Workbook_BeforeClose' VBA event handler for possible veto
2527 4 : if( !IsInPrepareClose() )
2528 : {
2529 : try
2530 : {
2531 2 : uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( aDocument.GetVbaEventProcessor(), uno::UNO_SET_THROW );
2532 4 : uno::Sequence< uno::Any > aArgs;
2533 4 : xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs );
2534 : }
2535 0 : catch( util::VetoException& )
2536 : {
2537 : // if event processor throws VetoException, macro has vetoed close
2538 0 : return false;
2539 : }
2540 0 : catch( uno::Exception& )
2541 : {
2542 : }
2543 : }
2544 : // end handler code
2545 :
2546 4 : bool nRet = SfxObjectShell::PrepareClose( bUI );
2547 4 : if (nRet) // true == close
2548 4 : aDocument.EnableIdle(false); // Do not mess around with it anymore!
2549 :
2550 4 : return nRet;
2551 : }
2552 :
2553 0 : void ScDocShell::PrepareReload()
2554 : {
2555 0 : SfxObjectShell::PrepareReload(); // FIXME: Doesn't do a thing?
2556 :
2557 : // The Disconnect of DDE Links can trigger a Reschedule.
2558 : // If the DDE Links are not deleted before the Document dtor,
2559 : // the DDE Link Update for this Document can be triggered ofrom this Reschedule on Reload.
2560 : // This causes a hang.
2561 : //
2562 : // Thus: Disconnect the DDE Links of the old Document before Reload
2563 0 : aDocument.GetDocLinkManager().disconnectDdeLinks();
2564 0 : }
2565 :
2566 6 : OUString ScDocShell::GetOwnFilterName()
2567 : {
2568 6 : return OUString(pFilterSc50);
2569 : }
2570 :
2571 0 : OUString ScDocShell::GetHtmlFilterName()
2572 : {
2573 0 : return OUString(pFilterHtml);
2574 : }
2575 :
2576 8 : OUString ScDocShell::GetWebQueryFilterName()
2577 : {
2578 8 : return OUString(pFilterHtmlWebQ);
2579 : }
2580 :
2581 0 : OUString ScDocShell::GetAsciiFilterName()
2582 : {
2583 0 : return OUString(pFilterAscii);
2584 : }
2585 :
2586 0 : OUString ScDocShell::GetLotusFilterName()
2587 : {
2588 0 : return OUString(pFilterLotus);
2589 : }
2590 :
2591 0 : OUString ScDocShell::GetDBaseFilterName()
2592 : {
2593 0 : return OUString(pFilterDBase);
2594 : }
2595 :
2596 0 : OUString ScDocShell::GetDifFilterName()
2597 : {
2598 0 : return OUString(pFilterDif);
2599 : }
2600 :
2601 0 : bool ScDocShell::HasAutomaticTableName( const OUString& rFilter )
2602 : {
2603 : // sal_True for those filters that keep the default table name
2604 : // (which is language specific)
2605 :
2606 0 : return rFilter.equalsAscii( pFilterAscii )
2607 0 : || rFilter.equalsAscii( pFilterLotus )
2608 0 : || rFilter.equalsAscii( pFilterExcel4 )
2609 0 : || rFilter.equalsAscii( pFilterEx4Temp )
2610 0 : || rFilter.equalsAscii( pFilterDBase )
2611 0 : || rFilter.equalsAscii( pFilterDif )
2612 0 : || rFilter.equalsAscii( pFilterSylk )
2613 0 : || rFilter.equalsAscii( pFilterHtml )
2614 0 : || rFilter.equalsAscii( pFilterRtf );
2615 : }
2616 :
2617 : #if ! ENABLE_TELEPATHY
2618 2248 : ScDocFunc *ScDocShell::CreateDocFunc()
2619 : {
2620 2248 : return new ScDocFuncDirect( *this );
2621 : }
2622 : #else
2623 : ScCollaboration* ScDocShell::GetCollaboration()
2624 : {
2625 : return mpCollaboration;
2626 : }
2627 : #endif
2628 :
2629 0 : ScDocShell::ScDocShell( const ScDocShell& rShell ) :
2630 : SvRefBase(),
2631 : SotObject(),
2632 : SfxObjectShell( rShell.GetCreateMode() ),
2633 : SfxListener(),
2634 : aDocument ( SCDOCMODE_DOCUMENT, this ),
2635 : aDdeTextFmt(OUString("TEXT")),
2636 : nPrtToScreenFactor( 1.0 ),
2637 0 : pImpl ( new DocShell_Impl ),
2638 : bHeaderOn ( true ),
2639 : bFooterOn ( true ),
2640 : bIsEmpty ( true ),
2641 : bIsInUndo ( false ),
2642 : bDocumentModifiedPending( false ),
2643 : bUpdateEnabled ( true ),
2644 : nDocumentLock ( 0 ),
2645 : nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2646 : pOldAutoDBRange ( NULL ),
2647 : pDocHelper ( NULL ),
2648 : pAutoStyleList ( NULL ),
2649 : pPaintLockData ( NULL ),
2650 : pSolverSaveData ( NULL ),
2651 : pSheetSaveData ( NULL ),
2652 0 : pModificator ( NULL )
2653 : #if ENABLE_TELEPATHY
2654 : , mpCollaboration( new ScCollaboration( this ) )
2655 : #endif
2656 : {
2657 0 : SetPool( &SC_MOD()->GetPool() );
2658 :
2659 0 : bIsInplace = rShell.bIsInplace;
2660 :
2661 0 : pDocFunc = CreateDocFunc();
2662 :
2663 : // SetBaseModel needs exception handling
2664 0 : ScModelObj::CreateAndSet( this );
2665 :
2666 0 : StartListening(*this);
2667 0 : SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2668 0 : if (pStlPool)
2669 0 : StartListening(*pStlPool);
2670 :
2671 0 : GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
2672 0 : SetHelpId( HID_SCSHELL_DOCSH );
2673 :
2674 : // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2675 0 : }
2676 :
2677 2248 : ScDocShell::ScDocShell( const sal_uInt64 i_nSfxCreationFlags ) :
2678 : SfxObjectShell( i_nSfxCreationFlags ),
2679 : aDocument ( SCDOCMODE_DOCUMENT, this ),
2680 : aDdeTextFmt(OUString("TEXT")),
2681 : nPrtToScreenFactor( 1.0 ),
2682 2248 : pImpl ( new DocShell_Impl ),
2683 : bHeaderOn ( true ),
2684 : bFooterOn ( true ),
2685 : bIsEmpty ( true ),
2686 : bIsInUndo ( false ),
2687 : bDocumentModifiedPending( false ),
2688 : bUpdateEnabled ( true ),
2689 : nDocumentLock ( 0 ),
2690 : nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2691 : pOldAutoDBRange ( NULL ),
2692 : pDocHelper ( NULL ),
2693 : pAutoStyleList ( NULL ),
2694 : pPaintLockData ( NULL ),
2695 : pSolverSaveData ( NULL ),
2696 : pSheetSaveData ( NULL ),
2697 4496 : pModificator ( NULL )
2698 : #if ENABLE_TELEPATHY
2699 : , mpCollaboration( new ScCollaboration( this ) )
2700 : #endif
2701 : {
2702 2248 : SetPool( &SC_MOD()->GetPool() );
2703 :
2704 2248 : bIsInplace = (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
2705 : // Will be reset if not in place
2706 :
2707 2248 : pDocFunc = CreateDocFunc();
2708 :
2709 : // SetBaseModel needs exception handling
2710 2248 : ScModelObj::CreateAndSet( this );
2711 :
2712 2248 : StartListening(*this);
2713 2248 : SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2714 2248 : if (pStlPool)
2715 2248 : StartListening(*pStlPool);
2716 2248 : SetHelpId( HID_SCSHELL_DOCSH );
2717 :
2718 : aDocument.GetDBCollection()->SetRefreshHandler(
2719 2248 : LINK( this, ScDocShell, RefreshDBDataHdl ) );
2720 :
2721 : // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2722 2248 : }
2723 :
2724 6606 : ScDocShell::~ScDocShell()
2725 : {
2726 2202 : ResetDrawObjectShell(); // If the Drawing Layer still tries to access it, access it
2727 :
2728 2202 : SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2729 2202 : if (pStlPool)
2730 2202 : EndListening(*pStlPool);
2731 2202 : EndListening(*this);
2732 :
2733 2202 : delete pAutoStyleList;
2734 :
2735 2202 : SfxApplication *pSfxApp = SfxGetpApp();
2736 2202 : if ( pSfxApp->GetDdeService() ) // Delete DDE for Document
2737 0 : pSfxApp->RemoveDdeTopic( this );
2738 :
2739 2202 : delete pDocFunc;
2740 2202 : delete aDocument.mpUndoManager;
2741 2202 : aDocument.mpUndoManager = 0;
2742 2202 : delete pImpl;
2743 :
2744 2202 : delete pPaintLockData;
2745 :
2746 2202 : delete pSolverSaveData;
2747 2202 : delete pSheetSaveData;
2748 2202 : delete pOldAutoDBRange;
2749 :
2750 2202 : if (pModificator)
2751 : {
2752 : OSL_FAIL("The Modificator should not exist");
2753 0 : delete pModificator;
2754 : }
2755 : #if ENABLE_TELEPATHY
2756 : delete mpCollaboration;
2757 : #endif
2758 4404 : }
2759 :
2760 20256 : ::svl::IUndoManager* ScDocShell::GetUndoManager()
2761 : {
2762 20256 : return aDocument.GetUndoManager();
2763 : }
2764 :
2765 18636 : void ScDocShell::SetModified( bool bModified )
2766 : {
2767 18636 : if ( SfxObjectShell::IsEnableSetModified() )
2768 : {
2769 17430 : SfxObjectShell::SetModified( bModified );
2770 17430 : Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
2771 : }
2772 18636 : }
2773 :
2774 34318 : void ScDocShell::SetDocumentModified( bool bIsModified /* = true */ )
2775 : {
2776 : // BroadcastUno must also happen right away with pPaintLockData
2777 : // FIXME: Also for SetDrawModified, if Drawing is connected
2778 : // FIXME: Then own Hint?
2779 :
2780 34318 : if ( pPaintLockData && bIsModified )
2781 : {
2782 : // #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results
2783 : // of RecalcModeAlways formulas (like OFFSET) after modifying cells
2784 18452 : aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2785 18452 : aDocument.InvalidateTableArea(); // #i105279# needed here
2786 18452 : aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2787 :
2788 18452 : pPaintLockData->SetModified(); // Later on ...
2789 52770 : return;
2790 : }
2791 :
2792 15866 : SetDrawModified( bIsModified );
2793 :
2794 15866 : if ( bIsModified )
2795 : {
2796 15866 : if ( aDocument.IsAutoCalcShellDisabled() )
2797 340 : SetDocumentModifiedPending( true );
2798 : else
2799 : {
2800 15526 : SetDocumentModifiedPending( false );
2801 15526 : aDocument.InvalidateStyleSheetUsage();
2802 15526 : aDocument.InvalidateTableArea();
2803 15526 : aDocument.InvalidateLastTableOpParams();
2804 15526 : aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2805 15526 : if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
2806 0 : aDocument.CalcFormulaTree( true );
2807 15526 : PostDataChanged();
2808 :
2809 : // Detective AutoUpdate:
2810 : // Update if formulas were modified (DetectiveDirty) or the list contains
2811 : // "Trace Error" entries (Trace Error can look completely different
2812 : // after changes to non-formula cells).
2813 :
2814 15526 : ScDetOpList* pList = aDocument.GetDetOpList();
2815 15570 : if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
2816 15542 : pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
2817 : {
2818 6 : GetDocFunc().DetectiveRefresh(true); // sal_True = caused by automatic update
2819 : }
2820 15526 : aDocument.SetDetectiveDirty(false); // always reset, also if not refreshed
2821 : }
2822 :
2823 : // notify UNO objects after BCA_BRDCST_ALWAYS etc.
2824 15866 : aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2825 : }
2826 : }
2827 :
2828 : /**
2829 : * SetDrawModified - without Formula update
2830 : *
2831 : * Drawing also needs to be updated for the normal SetDocumentModified
2832 : * e.g.: when deleting tables etc.
2833 : */
2834 15990 : void ScDocShell::SetDrawModified( bool bIsModified /* = true */ )
2835 : {
2836 15990 : bool bUpdate = bIsModified != IsModified();
2837 :
2838 15990 : SetModified( bIsModified );
2839 :
2840 15990 : SfxBindings* pBindings = GetViewBindings();
2841 15990 : if (bUpdate)
2842 : {
2843 1182 : if (pBindings)
2844 : {
2845 368 : pBindings->Invalidate( SID_SAVEDOC );
2846 368 : pBindings->Invalidate( SID_DOC_MODIFIED );
2847 : }
2848 : }
2849 :
2850 15990 : if (bIsModified)
2851 : {
2852 15990 : if (pBindings)
2853 : {
2854 : // #i105960# Undo etc used to be volatile.
2855 : // They always have to be invalidated, including drawing layer or row height changes
2856 : // (but not while pPaintLockData is set).
2857 14924 : pBindings->Invalidate( SID_UNDO );
2858 14924 : pBindings->Invalidate( SID_REDO );
2859 14924 : pBindings->Invalidate( SID_REPEAT );
2860 : }
2861 :
2862 15990 : if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
2863 : {
2864 960 : aDocument.UpdateChartListenerCollection();
2865 960 : SfxGetpApp()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
2866 : }
2867 15990 : SC_MOD()->AnythingChanged();
2868 : }
2869 15990 : }
2870 :
2871 304 : void ScDocShell::SetInUndo(bool bSet)
2872 : {
2873 304 : bIsInUndo = bSet;
2874 304 : }
2875 :
2876 0 : void ScDocShell::GetDocStat( ScDocStat& rDocStat )
2877 : {
2878 0 : SfxPrinter* pPrinter = GetPrinter();
2879 :
2880 0 : aDocument.GetDocStat( rDocStat );
2881 0 : rDocStat.nPageCount = 0;
2882 :
2883 0 : if ( pPrinter )
2884 0 : for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
2885 : rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount +
2886 0 : (sal_uInt16) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
2887 0 : }
2888 :
2889 0 : SfxDocumentInfoDialog* ScDocShell::CreateDocumentInfoDialog(
2890 : vcl::Window *pParent, const SfxItemSet &rSet )
2891 : {
2892 0 : SfxDocumentInfoDialog* pDlg = new SfxDocumentInfoDialog( pParent, rSet );
2893 0 : ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
2894 :
2895 : // Only for statistics, if this Doc is shown; not from the Doc Manager
2896 0 : if( pDocSh == this )
2897 : {
2898 0 : ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
2899 : OSL_ENSURE(pFact, "ScAbstractFactory create fail!");
2900 0 : ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
2901 : OSL_ENSURE(ScDocStatPageCreate, "Tabpage create fail!");
2902 0 : pDlg->AddFontTabPage();
2903 : pDlg->AddTabPage( 42,
2904 0 : ScGlobal::GetRscString( STR_DOC_STAT ),
2905 : ScDocStatPageCreate,
2906 0 : NULL);
2907 : }
2908 0 : return pDlg;
2909 : }
2910 :
2911 1012 : vcl::Window* ScDocShell::GetActiveDialogParent()
2912 : {
2913 1012 : ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2914 1012 : if ( pViewSh )
2915 460 : return pViewSh->GetDialogParent();
2916 : else
2917 552 : return Application::GetDefDialogParent();
2918 : }
2919 :
2920 0 : void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
2921 : {
2922 0 : delete pSolverSaveData;
2923 0 : pSolverSaveData = new ScOptSolverSave( rData );
2924 0 : }
2925 :
2926 8732 : ScSheetSaveData* ScDocShell::GetSheetSaveData()
2927 : {
2928 8732 : if (!pSheetSaveData)
2929 330 : pSheetSaveData = new ScSheetSaveData;
2930 :
2931 8732 : return pSheetSaveData;
2932 : }
2933 :
2934 : namespace {
2935 :
2936 0 : void removeKeysIfExists(Reference<ui::XAcceleratorConfiguration>& xScAccel, const vector<const awt::KeyEvent*>& rKeys)
2937 : {
2938 0 : vector<const awt::KeyEvent*>::const_iterator itr = rKeys.begin(), itrEnd = rKeys.end();
2939 0 : for (; itr != itrEnd; ++itr)
2940 : {
2941 0 : const awt::KeyEvent* p = *itr;
2942 0 : if (!p)
2943 0 : continue;
2944 :
2945 : try
2946 : {
2947 0 : xScAccel->removeKeyEvent(*p);
2948 : }
2949 0 : catch (const container::NoSuchElementException&) {}
2950 : }
2951 0 : }
2952 :
2953 : }
2954 :
2955 0 : void ScDocShell::ResetKeyBindings( ScOptionsUtil::KeyBindingType eType )
2956 : {
2957 : using namespace ::com::sun::star::ui;
2958 :
2959 0 : Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2960 0 : if (!xContext.is())
2961 0 : return;
2962 :
2963 : Reference<XModuleUIConfigurationManagerSupplier> xModuleCfgSupplier(
2964 0 : theModuleUIConfigurationManagerSupplier::get(xContext) );
2965 :
2966 : // Grab the Calc configuration.
2967 : Reference<XUIConfigurationManager> xConfigMgr =
2968 0 : xModuleCfgSupplier->getUIConfigurationManager(
2969 0 : OUString("com.sun.star.sheet.SpreadsheetDocument"));
2970 :
2971 0 : if (!xConfigMgr.is())
2972 0 : return;
2973 :
2974 : // shortcut manager
2975 0 : Reference<XAcceleratorConfiguration> xScAccel = xConfigMgr->getShortCutManager();
2976 :
2977 0 : if (!xScAccel.is())
2978 0 : return;
2979 :
2980 0 : vector<const awt::KeyEvent*> aKeys;
2981 0 : aKeys.reserve(4);
2982 :
2983 : // Backsapce key
2984 0 : awt::KeyEvent aBackspace;
2985 0 : aBackspace.KeyCode = awt::Key::BACKSPACE;
2986 0 : aBackspace.Modifiers = 0;
2987 0 : aKeys.push_back(&aBackspace);
2988 :
2989 : // Delete key
2990 0 : awt::KeyEvent aDelete;
2991 0 : aDelete.KeyCode = awt::Key::DELETE;
2992 0 : aDelete.Modifiers = 0;
2993 0 : aKeys.push_back(&aDelete);
2994 :
2995 : // Ctrl-D
2996 0 : awt::KeyEvent aCtrlD;
2997 0 : aCtrlD.KeyCode = awt::Key::D;
2998 0 : aCtrlD.Modifiers = awt::KeyModifier::MOD1;
2999 0 : aKeys.push_back(&aCtrlD);
3000 :
3001 : // Alt-Down
3002 0 : awt::KeyEvent aAltDown;
3003 0 : aAltDown.KeyCode = awt::Key::DOWN;
3004 0 : aAltDown.Modifiers = awt::KeyModifier::MOD2;
3005 0 : aKeys.push_back(&aAltDown);
3006 :
3007 : // Remove all involved keys first, because swapping commands don't work
3008 : // well without doing this.
3009 0 : removeKeysIfExists(xScAccel, aKeys);
3010 0 : xScAccel->store();
3011 :
3012 0 : switch (eType)
3013 : {
3014 : case ScOptionsUtil::KEY_DEFAULT:
3015 0 : xScAccel->setKeyEvent(aDelete, OUString(".uno:ClearContents"));
3016 0 : xScAccel->setKeyEvent(aBackspace, OUString(".uno:Delete"));
3017 0 : xScAccel->setKeyEvent(aCtrlD, OUString(".uno:FillDown"));
3018 0 : xScAccel->setKeyEvent(aAltDown, OUString(".uno:DataSelect"));
3019 0 : break;
3020 : case ScOptionsUtil::KEY_OOO_LEGACY:
3021 0 : xScAccel->setKeyEvent(aDelete, OUString(".uno:Delete"));
3022 0 : xScAccel->setKeyEvent(aBackspace, OUString(".uno:ClearContents"));
3023 0 : xScAccel->setKeyEvent(aCtrlD, OUString(".uno:DataSelect"));
3024 0 : break;
3025 : default:
3026 : ;
3027 : }
3028 :
3029 0 : xScAccel->store();
3030 : }
3031 :
3032 4 : void ScDocShell::UseSheetSaveEntries()
3033 : {
3034 4 : if (pSheetSaveData)
3035 : {
3036 2 : pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
3037 :
3038 2 : bool bHasEntries = false;
3039 2 : SCTAB nTabCount = aDocument.GetTableCount();
3040 : SCTAB nTab;
3041 4 : for (nTab = 0; nTab < nTabCount; ++nTab)
3042 2 : if (pSheetSaveData->HasStreamPos(nTab))
3043 0 : bHasEntries = true;
3044 :
3045 2 : if (!bHasEntries)
3046 : {
3047 : // if no positions were set (for example, export to other format),
3048 : // reset all "valid" flags
3049 :
3050 4 : for (nTab = 0; nTab < nTabCount; ++nTab)
3051 2 : if (aDocument.IsStreamValid(nTab))
3052 0 : aDocument.SetStreamValid(nTab, false);
3053 : }
3054 : }
3055 4 : }
3056 :
3057 : // --- ScDocShellModificator ------------------------------------------
3058 :
3059 76672 : ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
3060 : :
3061 : rDocShell( rDS ),
3062 76672 : mpProtector(new ScRefreshTimerProtector(rDS.GetDocument().GetRefreshTimerControlAddress()))
3063 : {
3064 76672 : ScDocument& rDoc = rDocShell.GetDocument();
3065 76672 : bAutoCalcShellDisabled = rDoc.IsAutoCalcShellDisabled();
3066 76672 : bIdleEnabled = rDoc.IsIdleEnabled();
3067 76672 : rDoc.SetAutoCalcShellDisabled( true );
3068 76672 : rDoc.EnableIdle(false);
3069 76672 : }
3070 :
3071 153344 : ScDocShellModificator::~ScDocShellModificator()
3072 : {
3073 76672 : ScDocument& rDoc = rDocShell.GetDocument();
3074 76672 : rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3075 76672 : if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
3076 268 : rDocShell.SetDocumentModified(); // last one shuts off the lights
3077 76672 : rDoc.EnableIdle(bIdleEnabled);
3078 76672 : }
3079 :
3080 49464 : void ScDocShellModificator::SetDocumentModified()
3081 : {
3082 49464 : ScDocument& rDoc = rDocShell.GetDocument();
3083 49464 : rDoc.ClearFormulaContext();
3084 49464 : if ( !rDoc.IsImportingXML() )
3085 : {
3086 : // AutoCalcShellDisabled temporaer restaurieren
3087 21066 : bool bDisabled = rDoc.IsAutoCalcShellDisabled();
3088 21066 : rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3089 21066 : rDocShell.SetDocumentModified();
3090 21066 : rDoc.SetAutoCalcShellDisabled( bDisabled );
3091 : }
3092 : else
3093 : {
3094 : // uno broadcast is necessary for api to work
3095 : // -> must also be done during xml import
3096 28398 : rDoc.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
3097 : }
3098 49464 : }
3099 :
3100 0 : bool ScDocShell::IsChangeRecording() const
3101 : {
3102 0 : ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3103 0 : return pChangeTrack != NULL;
3104 : }
3105 :
3106 0 : bool ScDocShell::HasChangeRecordProtection() const
3107 : {
3108 0 : bool bRes = false;
3109 0 : ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3110 0 : if (pChangeTrack)
3111 0 : bRes = pChangeTrack->IsProtected();
3112 0 : return bRes;
3113 : }
3114 :
3115 0 : void ScDocShell::SetChangeRecording( bool bActivate )
3116 : {
3117 0 : bool bOldChangeRecording = IsChangeRecording();
3118 :
3119 0 : if (bActivate)
3120 : {
3121 0 : aDocument.StartChangeTracking();
3122 0 : ScChangeViewSettings aChangeViewSet;
3123 0 : aChangeViewSet.SetShowChanges(true);
3124 0 : aDocument.SetChangeViewSettings(aChangeViewSet);
3125 : }
3126 : else
3127 : {
3128 0 : aDocument.EndChangeTracking();
3129 0 : PostPaintGridAll();
3130 : }
3131 :
3132 0 : if (bOldChangeRecording != IsChangeRecording())
3133 : {
3134 0 : UpdateAcceptChangesDialog();
3135 : // Slots invalidieren
3136 0 : SfxBindings* pBindings = GetViewBindings();
3137 0 : if (pBindings)
3138 0 : pBindings->InvalidateAll(false);
3139 : }
3140 0 : }
3141 :
3142 0 : bool ScDocShell::SetProtectionPassword( const OUString &rNewPassword )
3143 : {
3144 0 : bool bRes = false;
3145 0 : ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3146 0 : if (pChangeTrack)
3147 : {
3148 0 : bool bProtected = pChangeTrack->IsProtected();
3149 :
3150 0 : if (!rNewPassword.isEmpty())
3151 : {
3152 : // when password protection is applied change tracking must always be active
3153 0 : SetChangeRecording( true );
3154 :
3155 0 : ::com::sun::star::uno::Sequence< sal_Int8 > aProtectionHash;
3156 0 : SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword );
3157 0 : pChangeTrack->SetProtection( aProtectionHash );
3158 : }
3159 : else
3160 : {
3161 0 : pChangeTrack->SetProtection( ::com::sun::star::uno::Sequence< sal_Int8 >() );
3162 : }
3163 0 : bRes = true;
3164 :
3165 0 : if ( bProtected != pChangeTrack->IsProtected() )
3166 : {
3167 0 : UpdateAcceptChangesDialog();
3168 0 : SetDocumentModified();
3169 : }
3170 : }
3171 :
3172 0 : return bRes;
3173 : }
3174 :
3175 0 : bool ScDocShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > &rPasswordHash )
3176 : {
3177 0 : bool bRes = false;
3178 0 : ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3179 0 : if (pChangeTrack && pChangeTrack->IsProtected())
3180 : {
3181 0 : rPasswordHash = pChangeTrack->GetProtection();
3182 0 : bRes = true;
3183 : }
3184 0 : return bRes;
3185 228 : }
3186 :
3187 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|