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