fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sc / source / ui / docshell / docsh.cxx
bloba93aea456625be74c47de5b9ebc4336b432c6df7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include "docsh.hxx"
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>
64 #include "scabstdlg.hxx"
65 #include <sot/formats.hxx>
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"
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>
126 #include <config_telepathy.h>
128 #if ENABLE_TELEPATHY
129 #include "sccollaboration.hxx"
130 #endif
132 #include <vector>
133 #include <boost/shared_ptr.hpp>
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;
142 // STATIC DATA -----------------------------------------------------------
144 // Filter names (like in sclib.cxx)
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)";
166 #define ScDocShell
167 #include "scslots.hxx"
169 SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell)
171 void ScDocShell::InitInterface_Impl()
175 // GlobalName of the current version:
176 SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SfxObjectShellFlags::STD_NORMAL, "scalc" )
178 TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: No TypeInfo?
180 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
188 if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
190 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
191 *pFormat = SotClipboardFormatId::STARCALC_60;
192 *pFullTypeName = OUString( ScResId( SCSTR_LONG_SCDOC_NAME ) );
193 *pShortTypeName = OUString( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
195 else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
197 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
198 *pFormat = bTemplate ? SotClipboardFormatId::STARCALC_8_TEMPLATE : SotClipboardFormatId::STARCALC_8;
199 *pFullTypeName = "calc8";
200 *pShortTypeName = ScResId(SCSTR_SHORT_SCDOC_NAME).toString();
202 else
204 OSL_FAIL("Which version?");
208 std::set<Color> ScDocShell::GetDocColors()
210 return aDocument.GetDocColors();
213 void ScDocShell::DoEnterHandler()
215 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
216 if (pViewSh)
217 if (pViewSh->GetViewData().GetDocShell() == this)
218 SC_MOD()->InputEnterHandler();
221 SCTAB ScDocShell::GetSaveTab()
223 SCTAB nTab = 0;
224 ScTabViewShell* pSh = GetBestViewShell();
225 if (pSh)
227 const ScMarkData& rMark = pSh->GetViewData().GetMarkData();
228 nTab = rMark.GetFirstSelected();
230 return nTab;
233 HiddenInformation ScDocShell::GetHiddenInformationState( HiddenInformation nStates )
235 // get global state like HiddenInformation::DOCUMENTVERSIONS
236 HiddenInformation nState = SfxObjectShell::GetHiddenInformationState( nStates );
238 if ( nStates & HiddenInformation::RECORDEDCHANGES )
240 if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
241 nState |= HiddenInformation::RECORDEDCHANGES;
243 if ( nStates & HiddenInformation::NOTES )
245 SCTAB nTableCount = aDocument.GetTableCount();
246 bool bFound = false;
247 for (SCTAB nTab = 0; nTab < nTableCount && !bFound; ++nTab)
249 if (aDocument.HasTabNotes(nTab)) //TODO:
250 bFound = true;
253 if (bFound)
254 nState |= HiddenInformation::NOTES;
257 return nState;
260 void ScDocShell::BeforeXMLLoading()
262 aDocument.EnableIdle(false);
264 // prevent unnecessary broadcasts and updates
265 OSL_ENSURE(pModificator == NULL, "The Modificator should not exist");
266 pModificator = new ScDocShellModificator( *this );
268 aDocument.SetImportingXML( true );
269 aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
270 aDocument.EnableUndo( false );
271 // prevent unnecessary broadcasts and "half way listeners"
272 aDocument.SetInsertingFromOtherDoc( true );
275 void ScDocShell::AfterXMLLoading(bool bRet)
277 if (GetCreateMode() != SfxObjectCreateMode::ORGANIZER)
279 UpdateLinks();
280 // don't prevent establishing of listeners anymore
281 aDocument.SetInsertingFromOtherDoc( false );
282 if ( bRet )
284 ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
285 if (pChartListener)
286 pChartListener->UpdateDirtyCharts();
288 // #95582#; set the table names of linked tables to the new path
289 SCTAB nTabCount = aDocument.GetTableCount();
290 for (SCTAB i = 0; i < nTabCount; ++i)
292 if (aDocument.IsLinked( i ))
294 OUString aName;
295 aDocument.GetName(i, aName);
296 OUString aLinkTabName = aDocument.GetLinkTab(i);
297 sal_Int32 nLinkTabNameLength = aLinkTabName.getLength();
298 sal_Int32 nNameLength = aName.getLength();
299 if (nLinkTabNameLength < nNameLength)
302 // remove the quottes on begin and end of the docname and restore the escaped quotes
303 const sal_Unicode* pNameBuffer = aName.getStr();
304 if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
305 ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
307 OUStringBuffer aDocURLBuffer;
308 bool bQuote = true; // Document name is always quoted
309 ++pNameBuffer;
310 while ( bQuote && *pNameBuffer )
312 if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
313 bQuote = false;
314 else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
315 aDocURLBuffer.append(*pNameBuffer); // If escaped quote: only quote in the name
316 ++pNameBuffer;
319 if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
321 sal_Int32 nIndex = nNameLength - nLinkTabNameLength;
322 INetURLObject aINetURLObject(aDocURLBuffer.makeStringAndClear());
323 if(aName.match( aLinkTabName, nIndex) &&
324 (aName[nIndex - 1] == '#') && // before the table name should be the # char
325 !aINetURLObject.HasError()) // the docname should be a valid URL
327 aName = ScGlobal::GetDocTabName( aDocument.GetLinkDoc( i ), aDocument.GetLinkTab( i ) );
328 aDocument.RenameTab(i, aName, true, true);
330 // else; nothing has to happen, because it is a user given name
332 // else; nothing has to happen, because it is a user given name
334 // else; nothing has to happen, because it is a user given name
336 // else; nothing has to happen, because it is a user given name
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 ScDPCollection* pDPCollection = aDocument.GetDPCollection();
343 if ( pDPCollection )
345 size_t nDPCount = pDPCollection->GetCount();
346 for (size_t nDP=0; nDP<nDPCount; ++nDP)
348 ScDPObject* pDPObj = (*pDPCollection)[nDP];
349 if (pDPObj->GetName().isEmpty())
350 pDPObj->SetName( pDPCollection->CreateNewName() );
355 else
356 aDocument.SetInsertingFromOtherDoc( false );
358 aDocument.SetImportingXML( false );
359 aDocument.EnableExecuteLink( true );
360 aDocument.EnableUndo( true );
361 bIsEmpty = false;
363 if (pModificator)
365 bool bRecalcState = aDocument.GetHardRecalcState();
366 //temporarily set hard-recalc to prevent calling ScFormulaCell::Notify()
367 //which will set the cells dirty.
368 aDocument.SetHardRecalcState(true);
369 delete pModificator;
370 aDocument.SetHardRecalcState(bRecalcState);
371 pModificator = NULL;
373 else
375 OSL_FAIL("The Modificator should exist");
378 aDocument.EnableIdle(true);
381 namespace {
383 class LoadMediumGuard
385 public:
386 explicit LoadMediumGuard(ScDocument* pDoc) :
387 mpDoc(pDoc)
389 mpDoc->SetLoadingMedium(true);
392 ~LoadMediumGuard()
394 mpDoc->SetLoadingMedium(false);
396 private:
397 ScDocument* mpDoc;
400 void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData )
402 if (!rData.mpDataStream)
403 return;
405 const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream;
406 if (!r.maRange.IsValid())
407 return;
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.
413 ScRange aTopRange = r.maRange;
414 aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
415 sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1;
416 if (r.maRange.aEnd.Row() == MAXROW)
417 // Unlimited range.
418 nLimit = 0;
420 sc::DataStream::MoveType eMove =
421 r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ?
422 sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN;
424 sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove, 0);
425 pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty);
426 sc::DocumentLinkManager& rMgr = rShell.GetDocument().GetDocLinkManager();
427 rMgr.setDataStream(pStrm);
432 bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
434 LoadMediumGuard aLoadGuard(&aDocument);
436 // MacroCallMode is no longer needed, state is kept in SfxObjectShell now
438 // no Seek(0) here - always loading from storage, GetInStream must not be called
440 BeforeXMLLoading();
442 ScXMLImportWrapper aImport(*this, pLoadMedium, xStor);
444 bool bRet = false;
445 ErrCode nError = ERRCODE_NONE;
446 aDocument.EnableAdjustHeight(false);
447 if (GetCreateMode() == SfxObjectCreateMode::ORGANIZER)
448 bRet = aImport.Import(ScXMLImportWrapper::STYLES, nError);
449 else
450 bRet = aImport.Import(ScXMLImportWrapper::ALL, nError);
452 if ( nError )
453 pLoadMedium->SetError( nError, OUString( OSL_LOG_PREFIX ) );
455 processDataStream(*this, aImport.GetImportPostProcessData());
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 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), uno::UNO_QUERY_THROW);
461 uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
463 Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
464 ScRecalcOptions nRecalcMode =
465 static_cast<ScRecalcOptions>(officecfg::Office::Calc::Formula::Load::ODFRecalcMode::get(xContext));
467 bool bHardRecalc = false;
468 if (nRecalcMode == RECALC_ASK)
470 OUString sProductName(utl::ConfigManager::getProductName());
471 if (aDocument.IsUserInteractionEnabled() && xDocProps->getGenerator().indexOf(sProductName) == -1)
473 // Generator is not LibreOffice. Ask if the user wants to perform
474 // full re-calculation.
475 ScopedVclPtrInstance<QueryBox> aBox(
476 GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
477 ScGlobal::GetRscString(STR_QUERY_FORMULA_RECALC_ONLOAD_ODS));
478 aBox->SetCheckBoxText(ScGlobal::GetRscString(STR_ALWAYS_PERFORM_SELECTED));
480 bHardRecalc = aBox->Execute() == RET_YES;
482 if (aBox->GetCheckBoxState())
484 // Always perform selected action in the future.
485 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
486 officecfg::Office::Calc::Formula::Load::ODFRecalcMode::set(sal_Int32(0), batch);
487 ScFormulaOptions aOpt = SC_MOD()->GetFormulaOptions();
488 aOpt.SetODFRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER);
489 /* XXX is this really supposed to set the ScModule options?
490 * Not the ScDocShell options? */
491 SC_MOD()->SetFormulaOptions(aOpt);
493 batch->commit();
497 else if (nRecalcMode == RECALC_ALWAYS)
498 bHardRecalc = true;
500 if (bHardRecalc)
501 DoHardRecalc(false);
502 else
504 // still need to recalc volatile formula cells.
505 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
508 AfterXMLLoading(bRet);
510 aDocument.EnableAdjustHeight(true);
511 return bRet;
514 bool ScDocShell::SaveXML( SfxMedium* pSaveMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
516 aDocument.EnableIdle(false);
518 ScXMLImportWrapper aImport(*this, pSaveMedium, xStor);
519 bool bRet(false);
520 if (GetCreateMode() != SfxObjectCreateMode::ORGANIZER)
521 bRet = aImport.Export(false);
522 else
523 bRet = aImport.Export(true);
525 aDocument.EnableIdle(true);
527 return bRet;
530 bool ScDocShell::SaveCurrentChart( SfxMedium& rMedium )
532 bool bRet = false;
537 uno::Reference< lang::XComponent > xCurrentComponent = frame::Desktop::create( comphelper::getProcessComponentContext() )->getCurrentComponent();
539 uno::Reference< frame::XStorable2 > xStorable( xCurrentComponent, uno::UNO_QUERY_THROW );
541 uno::Reference< frame::XModel > xChartDoc ( xCurrentComponent, uno::UNO_QUERY_THROW );
543 ScXMLChartExportWrapper aExport( xChartDoc, rMedium );
544 bRet = aExport.Export();
546 catch(...)
548 SAL_WARN("sc", "exception thrown while saving chart. Bug!!!");
550 return bRet;
553 bool ScDocShell::Load( SfxMedium& rMedium )
555 LoadMediumGuard aLoadGuard(&aDocument);
556 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
558 // only the latin script language is loaded
559 // -> initialize the others from options (before loading)
560 InitOptions(true);
562 GetUndoManager()->Clear();
564 bool bRet = SfxObjectShell::Load( rMedium );
565 if( bRet )
567 if (GetMedium())
569 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
570 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
574 // prepare a valid document for XML filter
575 // (for ConvertFrom, InitNew is called before)
576 aDocument.MakeTable(0);
577 aDocument.GetStyleSheetPool()->CreateStandardStyles();
578 aDocument.UpdStlShtPtrsFrmNms();
580 bRet = LoadXML( &rMedium, NULL );
584 if (!bRet && !rMedium.GetError())
585 rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, OUString( OSL_LOG_PREFIX ) );
587 if (rMedium.GetError())
588 SetError( rMedium.GetError(), OUString( OSL_LOG_PREFIX ) );
590 InitItems();
591 CalcOutputFactor();
593 // invalidate eventually temporary table areas
594 if ( bRet )
595 aDocument.InvalidateTableArea();
597 bIsEmpty = false;
598 FinishedLoading( SfxLoadedFlags::ALL );
599 return bRet;
602 void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
604 const ScTablesHint* pScHint = dynamic_cast< const ScTablesHint* >( &rHint );
605 if (pScHint)
607 if (pScHint->GetId() == SC_TAB_INSERTED)
609 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor();
610 if ( xVbaEvents.is() ) try
612 uno::Sequence< uno::Any > aArgs( 1 );
613 aArgs[0] <<= pScHint->GetTab1();
614 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs );
616 catch( uno::Exception& )
622 if ( dynamic_cast<const SfxSimpleHint*>(&rHint) ) // Without parameter
624 sal_uLong nSlot = static_cast<const SfxSimpleHint&>(rHint).GetId();
625 switch ( nSlot )
627 case SFX_HINT_TITLECHANGED:
628 aDocument.SetName( SfxShell::GetName() );
629 // RegisterNewTargetNames gibts nicht mehr
630 SfxGetpApp()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
631 break;
634 else if ( dynamic_cast<const SfxStyleSheetHint*>(&rHint) ) // Template changed
635 NotifyStyle( static_cast<const SfxStyleSheetHint&>(rHint) );
636 else if ( dynamic_cast<const ScAutoStyleHint*>(&rHint) )
638 //! direct call for AutoStyles
640 // this is called synchronously from ScInterpreter::ScStyle,
641 // modifying the document must be asynchronous
642 // (handled by AddInitial)
644 const ScAutoStyleHint& rStlHint = static_cast<const ScAutoStyleHint&>(rHint);
645 ScRange aRange = rStlHint.GetRange();
646 OUString aName1 = rStlHint.GetStyle1();
647 OUString aName2 = rStlHint.GetStyle2();
648 sal_uInt32 nTimeout = rStlHint.GetTimeout();
650 if (!pAutoStyleList)
651 pAutoStyleList = new ScAutoStyleList(this);
652 pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 );
654 else if ( dynamic_cast<const SfxEventHint*>(&rHint) )
656 sal_uLong nEventId = static_cast<const SfxEventHint*>(&rHint)->GetEventId();
657 switch ( nEventId )
659 case SFX_EVENT_LOADFINISHED:
661 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
662 // the readonly documents should not be opened in shared mode
663 if ( HasSharedXMLFlagSet() && !SC_MOD()->IsInSharedDocLoading() && !IsReadOnly() )
665 if ( SwitchToShared( true, false ) )
667 ScViewData* pViewData = GetViewData();
668 ScTabView* pTabView = ( pViewData ? dynamic_cast< ScTabView* >( pViewData->GetView() ) : NULL );
669 if ( pTabView )
671 pTabView->UpdateLayerLocks();
674 else
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 SetReadOnlyUI( true );
681 #endif
683 break;
684 case SFX_EVENT_VIEWCREATED:
686 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
687 if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() )
689 ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
690 if ( aAppOptions.GetShowSharedDocumentWarning() )
692 ScopedVclPtrInstance<WarningBox> aBox( GetActiveDialogParent(), WinBits( WB_OK ),
693 ScGlobal::GetRscString( STR_SHARED_DOC_WARNING ) );
694 aBox->SetDefaultCheckBoxText();
695 aBox->Execute();
696 bool bChecked = aBox->GetCheckBoxState();
697 if ( bChecked )
699 aAppOptions.SetShowSharedDocumentWarning( !bChecked );
700 SC_MOD()->SetAppOptions( aAppOptions );
704 #endif
707 uno::Reference< uno::XComponentContext > xContext(
708 comphelper::getProcessComponentContext() );
709 uno::Reference< lang::XMultiServiceFactory > xServiceManager(
710 xContext->getServiceManager(),
711 uno::UNO_QUERY_THROW );
712 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xServiceManager, uno::UNO_QUERY_THROW );
713 uno::Reference< container::XEnumeration> xEnum = xEnumAccess->createContentEnumeration(
714 OUString( "com.sun.star.sheet.SpreadsheetDocumentJob" ) );
715 if ( xEnum.is() )
717 while ( xEnum->hasMoreElements() )
719 uno::Any aAny = xEnum->nextElement();
720 uno::Reference< lang::XSingleComponentFactory > xFactory;
721 aAny >>= xFactory;
722 if ( xFactory.is() )
724 uno::Reference< task::XJob > xJob( xFactory->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
725 uno::Sequence< beans::NamedValue > aArgsForJob(1);
726 ScViewData* pViewData = GetViewData();
727 SfxViewShell* pViewShell = ( pViewData ? pViewData->GetViewShell() : NULL );
728 SfxViewFrame* pViewFrame = ( pViewShell ? pViewShell->GetViewFrame() : NULL );
729 SfxFrame* pFrame = ( pViewFrame ? &pViewFrame->GetFrame() : NULL );
730 uno::Reference< frame::XController > xController = ( pFrame ? pFrame->GetController() : 0 );
731 uno::Reference< sheet::XSpreadsheetView > xSpreadsheetView( xController, uno::UNO_QUERY_THROW );
732 aArgsForJob[0] = beans::NamedValue( OUString( "SpreadsheetView" ),
733 uno::makeAny( xSpreadsheetView ) );
734 xJob->execute( aArgsForJob );
739 catch ( uno::Exception & )
743 break;
744 case SFX_EVENT_SAVEDOC:
746 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
747 if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
749 bool bSuccess = false;
750 bool bRetry = true;
751 while ( bRetry )
753 bRetry = false;
754 uno::Reference< frame::XModel > xModel;
757 // load shared file
758 xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
759 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
761 // check if shared flag is set in shared file
762 bool bShared = false;
763 ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
764 ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : NULL );
765 if ( pSharedDocShell )
767 bShared = pSharedDocShell->HasSharedXMLFlagSet();
770 // #i87870# check if shared status was disabled and enabled again
771 bool bOwnEntry = false;
772 bool bEntriesNotAccessible = false;
775 ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
776 bOwnEntry = aControlFile.HasOwnEntry();
778 catch ( uno::Exception& )
780 bEntriesNotAccessible = true;
783 if ( bShared && bOwnEntry )
785 uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
787 if ( xStorable->isReadonly() )
789 xCloseable->close( sal_True );
791 OUString aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
792 bool bNoLockAccess = false;
795 ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
796 LockFileEntry aData = aLockFile.GetLockData();
797 if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
799 aUserName = aData[LockFileComponent::OOOUSERNAME];
801 else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() )
803 aUserName = aData[LockFileComponent::SYSUSERNAME];
806 catch ( uno::Exception& )
808 bNoLockAccess = true;
811 if ( bNoLockAccess )
813 // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
814 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
816 else
818 OUString aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
819 aMessage = aMessage.replaceFirst( "%1", aUserName );
821 ScopedVclPtrInstance< WarningBox > aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
822 if ( aBox->Execute() == RET_RETRY )
824 bRetry = true;
828 else
830 // merge changes from shared file into temp file
831 bool bSaveToShared = false;
832 if ( pSharedDocShell )
834 bSaveToShared = MergeSharedDocument( pSharedDocShell );
837 // close shared file
838 xCloseable->close( sal_True );
840 // TODO: keep file lock on shared file
842 // store to shared file
843 if ( bSaveToShared )
845 bool bChangedViewSettings = false;
846 ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
847 if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
849 pChangeViewSet->SetShowChanges( false );
850 pChangeViewSet->SetShowAccepted( false );
851 aDocument.SetChangeViewSettings( *pChangeViewSet );
852 bChangedViewSettings = true;
855 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 uno::Sequence< beans::PropertyValue > aValues(1);
858 aValues[0].Name = "FilterName";
859 aValues[0].Value <<= OUString( GetMedium()->GetFilter()->GetFilterName() );
861 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, false);
862 if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
864 aValues.realloc( 2 );
865 aValues[1].Name = "Password";
866 aValues[1].Value <<= pPasswordItem->GetValue();
869 SC_MOD()->SetInSharedDocSaving( true );
870 xStor->storeToURL( GetSharedFileURL(), aValues );
871 SC_MOD()->SetInSharedDocSaving( false );
873 if ( bChangedViewSettings )
875 pChangeViewSet->SetShowChanges( true );
876 pChangeViewSet->SetShowAccepted( true );
877 aDocument.SetChangeViewSettings( *pChangeViewSet );
881 bSuccess = true;
882 GetUndoManager()->Clear();
885 else
887 xCloseable->close( sal_True );
889 if ( bEntriesNotAccessible )
891 // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
892 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
894 else
896 ScopedVclPtrInstance<WarningBox> aBox( GetActiveDialogParent(), WinBits( WB_OK ),
897 ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
898 aBox->Execute();
900 SfxBindings* pBindings = GetViewBindings();
901 if ( pBindings )
903 pBindings->ExecuteSynchron( SID_SAVEASDOC );
908 catch ( uno::Exception& )
910 OSL_FAIL( "SFX_EVENT_SAVEDOC: caught exception\n" );
911 SC_MOD()->SetInSharedDocSaving( false );
915 uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
916 xClose->close( sal_True );
918 catch ( uno::Exception& )
924 if ( !bSuccess )
925 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
927 #endif
929 if (pSheetSaveData)
930 pSheetSaveData->SetInSupportedSave(true);
932 break;
933 case SFX_EVENT_SAVEASDOC:
935 if ( GetDocument().GetExternalRefManager()->containsUnsavedReferences() )
937 ScopedVclPtrInstance<WarningBox> aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
938 ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
940 if( RET_NO == aBox->Execute())
942 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
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 if (pSheetSaveData)
951 pSheetSaveData->SetInSupportedSave(true);
952 break;
953 case SFX_EVENT_SAVEDOCDONE:
954 case SFX_EVENT_SAVEASDOCDONE:
956 // new positions are used after "save" and "save as", but not "save to"
957 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 if (pSheetSaveData)
962 pSheetSaveData->SetInSupportedSave(false);
963 break;
964 default:
967 break;
972 // Load contents for organizer
973 bool ScDocShell::LoadFrom( SfxMedium& rMedium )
975 LoadMediumGuard aLoadGuard(&aDocument);
976 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
978 WaitObject aWait( GetActiveDialogParent() );
980 bool bRet = false;
982 if (GetMedium())
984 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
985 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
988 // until loading/saving only the styles in XML is implemented,
989 // load the whole file
990 bRet = LoadXML( &rMedium, NULL );
991 InitItems();
993 SfxObjectShell::LoadFrom( rMedium );
995 return bRet;
998 static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert)
1000 OUStringBuffer aBuf;
1001 std::vector< OUString > aTokens;
1002 sal_Int32 n = rOption.getLength();
1003 const sal_Unicode* p = rOption.getStr();
1004 for (sal_Int32 i = 0; i < n; ++i)
1006 const sal_Unicode c = p[i];
1007 if (c == ' ')
1009 if (!aBuf.isEmpty())
1010 aTokens.push_back( aBuf.makeStringAndClear() );
1012 else
1013 aBuf.append(c);
1016 if (!aBuf.isEmpty())
1017 aTokens.push_back( aBuf.makeStringAndClear() );
1019 rLang = LanguageType( 0 );
1020 rDateConvert = false;
1022 if (aTokens.size() > 0)
1023 rLang = static_cast<LanguageType>(aTokens[0].toInt32());
1024 if (aTokens.size() > 1)
1025 rDateConvert = static_cast<bool>(aTokens[1].toInt32());
1028 bool ScDocShell::ConvertFrom( SfxMedium& rMedium )
1030 LoadMediumGuard aLoadGuard(&aDocument);
1032 bool bRet = false; // sal_False means user quit!
1033 // On error: Set error at stream
1035 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1037 GetUndoManager()->Clear();
1039 // Set optimal col width after import?
1040 bool bSetColWidths = false;
1041 bool bSetSimpleTextColWidths = false;
1042 ScColWidthParam aColWidthParam[MAXCOLCOUNT];
1043 ScRange aColWidthRange;
1044 // Set optimal row height after import?
1045 bool bSetRowHeights = false;
1047 vector<ScDocRowHeightUpdater::TabRanges> aRecalcRowRangesArray;
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 rMedium.GetPhysicalName(); //! Call CreateFileStream directly, if available
1053 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
1054 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
1056 const SfxFilter* pFilter = rMedium.GetFilter();
1057 if (pFilter)
1059 OUString aFltName = pFilter->GetFilterName();
1061 bool bCalc3 = aFltName == "StarCalc 3.0";
1062 bool bCalc4 = aFltName == "StarCalc 4.0";
1063 if (!bCalc3 && !bCalc4)
1064 aDocument.SetInsertingFromOtherDoc( true );
1066 if (aFltName == pFilterXML)
1067 bRet = LoadXML( &rMedium, NULL );
1068 else if (aFltName == "StarCalc 1.0")
1070 SvStream* pStream = rMedium.GetInStream();
1071 if (pStream)
1073 FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
1074 if (eError != eERR_OK)
1076 if (!GetError())
1077 SetError(eError, OUString( OSL_LOG_PREFIX ));
1079 else
1080 bRet = true;
1083 else if (aFltName == pFilterLotus)
1085 OUString sItStr;
1086 SfxItemSet* pSet = rMedium.GetItemSet();
1087 const SfxPoolItem* pItem;
1088 if ( pSet && SfxItemState::SET ==
1089 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1091 sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1094 if (sItStr.isEmpty())
1096 // default for lotus import (from API without options):
1097 // IBM_437 encoding
1098 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
1101 FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
1102 ScGlobal::GetCharsetValue(sItStr));
1103 if (eError != eERR_OK)
1105 if (!GetError())
1106 SetError(eError, OUString( OSL_LOG_PREFIX ));
1108 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1109 bRet = true;
1111 else
1112 bRet = true;
1113 bSetColWidths = true;
1114 bSetRowHeights = true;
1116 else if ( aFltName == pFilterExcel4 || aFltName == pFilterExcel5 ||
1117 aFltName == pFilterExcel95 || aFltName == pFilterExcel97 ||
1118 aFltName == pFilterEx4Temp || aFltName == pFilterEx5Temp ||
1119 aFltName == pFilterEx95Temp || aFltName == pFilterEx97Temp )
1121 EXCIMPFORMAT eFormat = EIF_AUTO;
1122 if ( aFltName == pFilterExcel4 || aFltName == pFilterEx4Temp )
1123 eFormat = EIF_BIFF_LE4;
1124 else if ( aFltName == pFilterExcel5 || aFltName == pFilterExcel95 ||
1125 aFltName == pFilterEx5Temp || aFltName == pFilterEx95Temp )
1126 eFormat = EIF_BIFF5;
1127 else if ( aFltName == pFilterExcel97 || aFltName == pFilterEx97Temp )
1128 eFormat = EIF_BIFF8;
1130 MakeDrawLayer(); //! In the filter
1131 CalcOutputFactor(); // prepare update of row height
1132 FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
1133 aDocument.UpdateFontCharSet();
1134 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
1135 aDocument.UpdateChartListenerCollection(); //! For all imports?
1137 // all graphics objects must have names
1138 aDocument.EnsureGraphicNames();
1140 if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
1142 if (!GetError())
1143 SetError(eError, OUString( OSL_LOG_PREFIX ));
1144 bRet = true;
1146 else if (eError != eERR_OK)
1148 if (!GetError())
1149 SetError(eError, OUString( OSL_LOG_PREFIX ));
1151 else
1152 bRet = true;
1154 else if (aFltName == pFilterAscii)
1156 SfxItemSet* pSet = rMedium.GetItemSet();
1157 const SfxPoolItem* pItem;
1158 ScAsciiOptions aOptions;
1159 bool bOptInit = false;
1161 if ( pSet && SfxItemState::SET ==
1162 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1164 aOptions.ReadFromString( static_cast<const SfxStringItem*>(pItem)->GetValue() );
1165 bOptInit = true;
1168 if ( !bOptInit )
1170 // default for ascii import (from API without options):
1171 // ISO8859-1/MS_1252 encoding, comma, double quotes
1173 aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1174 aOptions.SetFieldSeps( OUString(',') );
1175 aOptions.SetTextSep( '"' );
1178 FltError eError = eERR_OK;
1179 bool bOverflowRow, bOverflowCol, bOverflowCell;
1180 bOverflowRow = bOverflowCol = bOverflowCell = false;
1182 if( ! rMedium.IsStorage() )
1184 ScImportExport aImpEx( &aDocument );
1185 aImpEx.SetExtOptions( aOptions );
1187 SvStream* pInStream = rMedium.GetInStream();
1188 if (pInStream)
1190 pInStream->SetStreamCharSet( aOptions.GetCharSet() );
1191 pInStream->Seek( 0 );
1192 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
1193 eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
1194 aDocument.StartAllListeners();
1195 sc::SetFormulaDirtyContext aCxt;
1196 aDocument.SetAllFormulasDirty(aCxt);
1197 INetURLObject aURLObjForDefaultNameSheetName(rMedium.GetName());
1198 aDocument.RenameTab(0,aURLObjForDefaultNameSheetName.GetBase());
1199 bOverflowRow = aImpEx.IsOverflowRow();
1200 bOverflowCol = aImpEx.IsOverflowCol();
1201 bOverflowCell = aImpEx.IsOverflowCell();
1203 else
1205 OSL_FAIL( "No Stream" );
1209 if (eError != eERR_OK)
1211 if (!GetError())
1212 SetError(eError, OUString( OSL_LOG_PREFIX ));
1214 else if (!GetError() && (bOverflowRow || bOverflowCol || bOverflowCell))
1216 // precedence: row, column, cell
1217 FltError nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW :
1218 (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW :
1219 SCWARN_IMPORT_CELL_OVERFLOW));
1220 SetError( nWarn, OUString( OSL_LOG_PREFIX ));
1222 bSetColWidths = true;
1223 bSetSimpleTextColWidths = true;
1225 else if (aFltName == pFilterDBase)
1227 OUString sItStr;
1228 SfxItemSet* pSet = rMedium.GetItemSet();
1229 const SfxPoolItem* pItem;
1230 if ( pSet && SfxItemState::SET ==
1231 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1233 sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1236 if (sItStr.isEmpty())
1238 // default for dBase import (from API without options):
1239 // IBM_850 encoding
1241 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
1244 ScDocRowHeightUpdater::TabRanges aRecalcRanges(0);
1245 sal_uLong eError = DBaseImport( rMedium.GetPhysicalName(),
1246 ScGlobal::GetCharsetValue(sItStr), aColWidthParam, *aRecalcRanges.mpRanges );
1247 aRecalcRowRangesArray.push_back(aRecalcRanges);
1249 if (eError != eERR_OK)
1251 if (!GetError())
1252 SetError(eError, OUString( OSL_LOG_PREFIX ));
1253 bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
1255 else
1256 bRet = true;
1258 aColWidthRange.aStart.SetRow( 1 ); // Except for the column header
1259 bSetColWidths = true;
1260 bSetSimpleTextColWidths = true;
1262 else if (aFltName == pFilterDif)
1264 SvStream* pStream = rMedium.GetInStream();
1265 if (pStream)
1267 FltError eError;
1268 OUString sItStr;
1269 SfxItemSet* pSet = rMedium.GetItemSet();
1270 const SfxPoolItem* pItem;
1271 if ( pSet && SfxItemState::SET ==
1272 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1274 sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
1277 if (sItStr.isEmpty())
1279 // default for DIF import (from API without options):
1280 // ISO8859-1/MS_1252 encoding
1282 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
1285 eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
1286 ScGlobal::GetCharsetValue(sItStr));
1287 if (eError != eERR_OK)
1289 if (!GetError())
1290 SetError(eError, OUString( OSL_LOG_PREFIX ));
1292 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1293 bRet = true;
1295 else
1296 bRet = true;
1298 bSetColWidths = true;
1299 bSetSimpleTextColWidths = true;
1300 bSetRowHeights = true;
1302 else if (aFltName == pFilterSylk)
1304 FltError eError = SCERR_IMPORT_UNKNOWN;
1305 if( !rMedium.IsStorage() )
1307 ScImportExport aImpEx( &aDocument );
1309 SvStream* pInStream = rMedium.GetInStream();
1310 if (pInStream)
1312 pInStream->Seek( 0 );
1313 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SotClipboardFormatId::SYLK );
1314 eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
1315 aDocument.StartAllListeners();
1316 sc::SetFormulaDirtyContext aCxt;
1317 aDocument.SetAllFormulasDirty(aCxt);
1319 else
1321 OSL_FAIL( "No Stream" );
1325 if ( eError != eERR_OK && !GetError() )
1326 SetError(eError, OUString( OSL_LOG_PREFIX ));
1327 bSetColWidths = true;
1328 bSetSimpleTextColWidths = true;
1329 bSetRowHeights = true;
1331 else if (aFltName == pFilterQPro6)
1333 FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
1334 if (eError != eERR_OK)
1336 if (!GetError())
1337 SetError( eError, OUString( OSL_LOG_PREFIX ) );
1338 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1339 bRet = true;
1341 else
1342 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 bSetRowHeights = true;
1349 else if (aFltName == pFilterRtf)
1351 FltError eError = SCERR_IMPORT_UNKNOWN;
1352 if( !rMedium.IsStorage() )
1354 SvStream* pInStream = rMedium.GetInStream();
1355 if (pInStream)
1357 pInStream->Seek( 0 );
1358 ScRange aRange;
1359 eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
1360 if (eError != eERR_OK)
1362 if (!GetError())
1363 SetError(eError, OUString( OSL_LOG_PREFIX ));
1365 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1366 bRet = true;
1368 else
1369 bRet = true;
1370 aDocument.StartAllListeners();
1371 sc::SetFormulaDirtyContext aCxt;
1372 aDocument.SetAllFormulasDirty(aCxt);
1373 bSetColWidths = true;
1374 bSetRowHeights = true;
1376 else
1378 OSL_FAIL( "No Stream" );
1382 if ( eError != eERR_OK && !GetError() )
1383 SetError(eError, OUString( OSL_LOG_PREFIX ));
1385 else if (aFltName == pFilterHtml || aFltName == pFilterHtmlWebQ)
1387 FltError eError = SCERR_IMPORT_UNKNOWN;
1388 bool bWebQuery = aFltName == pFilterHtmlWebQ;
1389 if( !rMedium.IsStorage() )
1391 SvStream* pInStream = rMedium.GetInStream();
1392 if (pInStream)
1394 LanguageType eLang = LANGUAGE_SYSTEM;
1395 bool bDateConvert = false;
1396 SfxItemSet* pSet = rMedium.GetItemSet();
1397 const SfxPoolItem* pItem;
1398 if ( pSet && SfxItemState::SET ==
1399 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1401 OUString aFilterOption = (static_cast<const SfxStringItem*>(pItem))->GetValue();
1402 lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert);
1405 pInStream->Seek( 0 );
1406 ScRange aRange;
1407 // HTML does its own ColWidth/RowHeight
1408 CalcOutputFactor();
1409 SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eLang);
1410 eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
1411 GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert );
1412 if (eError != eERR_OK)
1414 if (!GetError())
1415 SetError(eError, OUString( OSL_LOG_PREFIX ));
1417 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1418 bRet = true;
1420 else
1421 bRet = true;
1422 aDocument.StartAllListeners();
1424 sc::SetFormulaDirtyContext aCxt;
1425 aDocument.SetAllFormulasDirty(aCxt);
1427 else
1429 OSL_FAIL( "No Stream" );
1433 if ( eError != eERR_OK && !GetError() )
1434 SetError(eError, OUString( OSL_LOG_PREFIX ));
1436 else
1438 if (!GetError())
1439 SetError(SCERR_IMPORT_NI, OUString( OSL_LOG_PREFIX ));
1442 if (!bCalc3)
1443 aDocument.SetInsertingFromOtherDoc( false );
1445 else
1447 OSL_FAIL("No Filter in ConvertFrom");
1450 InitItems();
1451 CalcOutputFactor();
1452 if ( bRet && (bSetColWidths || bSetRowHeights) )
1453 { // Adjust column width/row height; base 100% zoom
1454 Fraction aZoom( 1, 1 );
1455 double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom / GetOutputFactor(); // Factor is printer display ratio
1456 double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
1457 ScopedVclPtrInstance< VirtualDevice > pVirtDev;
1458 // all sheets (for Excel import)
1459 SCTAB nTabCount = aDocument.GetTableCount();
1460 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1462 SCCOL nEndCol;
1463 SCROW nEndRow;
1464 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1465 aColWidthRange.aEnd.SetCol( nEndCol );
1466 aColWidthRange.aEnd.SetRow( nEndRow );
1467 ScMarkData aMark;
1468 aMark.SetMarkArea( aColWidthRange );
1469 aMark.MarkToMulti();
1471 // Order is important: First width, then height
1472 if ( bSetColWidths )
1474 for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
1476 if (!bSetSimpleTextColWidths)
1477 aColWidthParam[nCol].mbSimpleText = false;
1479 sal_uInt16 nWidth = aDocument.GetOptimalColWidth(
1480 nCol, nTab, pVirtDev, nPPTX, nPPTY, aZoom, aZoom, false, &aMark,
1481 &aColWidthParam[nCol] );
1482 aDocument.SetColWidth( nCol, nTab,
1483 nWidth + (sal_uInt16)ScGlobal::nLastColWidthExtra );
1488 if (bSetRowHeights)
1490 // Update all rows in all tables.
1491 ScSizeDeviceProvider aProv(this);
1492 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), NULL);
1493 aUpdater.update();
1495 else if (!aRecalcRowRangesArray.empty())
1497 // Update only specified row ranges for better performance.
1498 ScSizeDeviceProvider aProv(this);
1499 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &aRecalcRowRangesArray);
1500 aUpdater.update();
1503 FinishedLoading( SfxLoadedFlags::ALL );
1505 // invalidate eventually temporary table areas
1506 if ( bRet )
1507 aDocument.InvalidateTableArea();
1509 bIsEmpty = false;
1511 return bRet;
1514 bool ScDocShell::LoadExternal( SfxMedium& rMed )
1516 const SfxFilter* pFilter = rMed.GetFilter();
1517 if (!pFilter)
1518 return false;
1520 if (pFilter->GetProviderName() == "orcus")
1522 ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
1523 if (!pOrcus)
1524 return false;
1526 const OUString& rFilterName = pFilter->GetName();
1527 if (rFilterName == "gnumeric")
1529 if (!pOrcus->importGnumeric(aDocument, rMed))
1530 return false;
1532 else if (rFilterName == "csv")
1534 if (!pOrcus->importCSV(aDocument, rMed))
1535 return false;
1537 else if (rFilterName == "xlsx")
1539 if (!pOrcus->importXLSX(aDocument, rMed))
1540 return false;
1542 else if (rFilterName == "ods")
1544 if (!pOrcus->importODS(aDocument, rMed))
1545 return false;
1548 FinishedLoading(SfxLoadedFlags::ALL);
1549 return true;
1552 return false;
1555 ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
1556 : mrDocShell( rDocShell)
1558 // DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
1560 ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
1561 if (pCharts)
1562 pCharts->UpdateDirtyCharts(); // Charts to be updated.
1563 mrDocShell.aDocument.StopTemporaryChartLock();
1564 if (mrDocShell.pAutoStyleList)
1565 mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
1566 if (mrDocShell.aDocument.HasExternalRefManager())
1568 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1569 if (pRefMgr && pRefMgr->hasExternalData())
1571 pRefMgr->setAllCacheTableReferencedStati( false);
1572 mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
1575 if (mrDocShell.GetCreateMode()== SfxObjectCreateMode::STANDARD)
1576 mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
1579 ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
1581 if (mrDocShell.aDocument.HasExternalRefManager())
1583 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1584 if (pRefMgr && pRefMgr->hasExternalData())
1586 // Prevent accidental data loss due to lack of knowledge.
1587 pRefMgr->setAllCacheTableReferencedStati( true);
1592 bool ScDocShell::Save()
1594 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1596 PrepareSaveGuard aPrepareGuard( *this);
1598 SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst( this );
1599 if (pFrame1)
1601 vcl::Window* pWindow = &pFrame1->GetWindow();
1602 if ( pWindow )
1604 vcl::Window* pSysWin = pWindow->GetSystemWindow();
1605 if ( pSysWin )
1607 pSysWin->SetAccessibleName(OUString());
1611 // wait cursor is handled with progress bar
1612 bool bRet = SfxObjectShell::Save();
1613 if( bRet )
1614 bRet = SaveXML( GetMedium(), NULL );
1615 return bRet;
1618 namespace {
1621 * Remove the file name from the full path, to keep only the directory path.
1623 void popFileName(OUString& rPath)
1625 if (!rPath.isEmpty())
1627 INetURLObject aURLObj(rPath);
1628 aURLObj.removeSegment();
1629 rPath = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
1635 bool ScDocShell::SaveAs( SfxMedium& rMedium )
1637 OUString aCurPath; // empty for new document that hasn't been saved.
1638 const SfxMedium* pCurMedium = GetMedium();
1639 if (pCurMedium)
1641 aCurPath = pCurMedium->GetName();
1642 popFileName(aCurPath);
1645 if (!aCurPath.isEmpty())
1647 // current document has a path -> not a brand-new document.
1648 OUString aNewPath = rMedium.GetName();
1649 popFileName(aNewPath);
1650 OUString aRel = URIHelper::simpleNormalizedMakeRelative(aCurPath, aNewPath);
1651 if (!aRel.isEmpty())
1653 // Directory path will change before and after the save.
1654 aDocument.InvalidateStreamOnSave();
1658 ScTabViewShell* pViewShell = GetBestViewShell();
1659 bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA1);
1660 if (bNeedsRehash)
1661 // legacy xls hash double-hashed by SHA1 is also supported.
1662 bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
1664 if (pViewShell && bNeedsRehash)
1666 if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1))
1667 // password re-type cancelled. Don't save the document.
1668 return false;
1671 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1673 PrepareSaveGuard aPrepareGuard( *this);
1675 OUString aFltName = rMedium.GetFilter()->GetFilterName();
1676 bool bChartExport = aFltName.indexOf("chart8") != -1;
1678 // wait cursor is handled with progress bar
1679 bool bRet = false;
1680 if(!bChartExport)
1682 bRet = SfxObjectShell::SaveAs( rMedium );
1683 if (bRet)
1684 bRet = SaveXML( &rMedium, NULL );
1686 else
1688 bRet = SaveCurrentChart( rMedium );
1691 return bRet;
1694 bool ScDocShell::IsInformationLost()
1696 //FIXME: If we have time build a correct own way how to handle this
1697 return SfxObjectShell::IsInformationLost();
1700 namespace {
1702 // Xcl-like column width measured in characters of standard font.
1703 sal_Int32 lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth )
1705 double f = nWidth;
1706 f *= 1328.0 / 25.0;
1707 f += 90.0;
1708 f *= 1.0 / 23.0;
1709 f /= 256.0;
1711 return sal_Int32( f );
1714 void lcl_ScDocShell_GetFixedWidthString( OUString& rStr, const ScDocument& rDoc,
1715 SCTAB nTab, SCCOL nCol, bool bValue, SvxCellHorJustify eHorJust )
1717 OUString aString = rStr;
1718 sal_Int32 nLen = lcl_ScDocShell_GetColWidthInChars(
1719 rDoc.GetColWidth( nCol, nTab ) );
1720 //If the text won't fit in the column
1721 if ( nLen < aString.getLength() )
1723 OUStringBuffer aReplacement;
1724 if (bValue)
1725 aReplacement.append("###");
1726 else
1727 aReplacement.append(aString);
1728 //truncate to the number of characters that should fit, even in the
1729 //bValue case nLen might be < len ###
1730 aString = comphelper::string::truncateToLength(aReplacement, nLen).makeStringAndClear();
1732 if ( nLen > aString.getLength() )
1734 if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
1735 eHorJust = SVX_HOR_JUSTIFY_RIGHT;
1736 sal_Int32 nBlanks = nLen - aString.getLength();
1737 switch ( eHorJust )
1739 case SVX_HOR_JUSTIFY_RIGHT:
1741 OUStringBuffer aTmp;
1742 aTmp = comphelper::string::padToLength( aTmp, nBlanks, ' ' );
1743 aString = aTmp.append(aString).makeStringAndClear();
1745 break;
1746 case SVX_HOR_JUSTIFY_CENTER:
1748 sal_Int32 nLeftPad = nBlanks / 2;
1749 OUStringBuffer aTmp;
1750 comphelper::string::padToLength( aTmp, nLeftPad, ' ' );
1751 aTmp.append(aString);
1752 comphelper::string::padToLength( aTmp, nLen, ' ' );
1753 aString = aTmp.makeStringAndClear();
1755 break;
1756 default:
1758 OUStringBuffer aTmp(aString);
1759 comphelper::string::padToLength( aTmp, nLen, ' ' );
1760 aString = aTmp.makeStringAndClear();
1764 rStr = aString;
1767 void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
1768 const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
1770 OUString aString;
1771 lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, false,
1772 SVX_HOR_JUSTIFY_STANDARD );
1773 rStream.WriteUnicodeOrByteText( aString );
1776 template<typename StrT, typename SepCharT>
1777 sal_Int32 getTextSepPos(
1778 const StrT& rStr, const ScImportOptions& rAsciiOpt, const SepCharT& rTextSep, const SepCharT& rFieldSep, bool& rNeedQuotes)
1780 // #i116636# quotes are needed if text delimiter (quote), field delimiter,
1781 // or LF is in the cell text.
1782 sal_Int32 nPos = rStr.indexOf(rTextSep);
1783 rNeedQuotes = rAsciiOpt.bQuoteAllText || (nPos >= 0) ||
1784 (rStr.indexOf(rFieldSep) >= 0) ||
1785 (rStr.indexOf('\n') >= 0);
1786 return nPos;
1789 template<typename StrT, typename StrBufT>
1790 void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr)
1792 while (nPos >= 0)
1794 StrBufT aBuf(rStr);
1795 aBuf.insert(nPos, rStrDelim);
1796 rStr = aBuf.makeStringAndClear();
1797 nPos = rStr.indexOf(rStrDelim, nPos+1+rStrDelim.getLength());
1803 void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
1805 sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
1806 sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
1807 rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet;
1808 bool bFixedWidth = rAsciiOpt.bFixedWidth;
1809 bool bSaveAsShown = rAsciiOpt.bSaveAsShown;
1810 bool bShowFormulas = rAsciiOpt.bSaveFormulas;
1812 rtl_TextEncoding eOldCharSet = rStream.GetStreamCharSet();
1813 rStream.SetStreamCharSet( eCharSet );
1814 SvStreamEndian nOldNumberFormatInt = rStream.GetEndian();
1815 OString aStrDelimEncoded; // only used if not Unicode
1816 OUString aStrDelimDecoded; // only used if context encoding
1817 OString aDelimEncoded;
1818 OUString aDelimDecoded;
1819 bool bContextOrNotAsciiEncoding;
1820 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
1822 rStream.StartWritingUnicodeText();
1823 bContextOrNotAsciiEncoding = false;
1825 else
1827 aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
1828 aDelimEncoded = OString(&cDelim, 1, eCharSet);
1829 rtl_TextEncodingInfo aInfo;
1830 aInfo.StructSize = sizeof(aInfo);
1831 if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
1833 bContextOrNotAsciiEncoding =
1834 (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
1835 ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
1836 if ( bContextOrNotAsciiEncoding )
1838 aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet);
1839 aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet);
1842 else
1843 bContextOrNotAsciiEncoding = false;
1846 SCCOL nStartCol = 0;
1847 SCROW nStartRow = 0;
1848 SCTAB nTab = GetSaveTab();
1849 SCCOL nEndCol;
1850 SCROW nEndRow;
1851 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1853 ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
1855 OUString aString;
1857 bool bTabProtect = aDocument.IsTabProtected( nTab );
1859 SCCOL nCol;
1860 SCROW nRow;
1861 SCCOL nNextCol = nStartCol;
1862 SCROW nNextRow = nStartRow;
1863 SCCOL nEmptyCol;
1864 SCROW nEmptyRow;
1865 SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
1867 ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
1868 nEndCol, nEndRow );
1869 ScRefCellValue* pCell;
1870 while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
1872 bool bProgress = false; // only upon line change
1873 if ( nNextRow < nRow )
1874 { // empty rows or/and empty columns up to end of row
1875 bProgress = true;
1876 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
1877 { // remaining columns of last row
1878 if ( bFixedWidth )
1879 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1880 aDocument, nTab, nEmptyCol );
1881 else if ( cDelim != 0 )
1882 rStream.WriteUniOrByteChar( cDelim );
1884 endlub( rStream );
1885 nNextRow++;
1886 for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
1887 { // completely empty rows
1888 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
1890 if ( bFixedWidth )
1891 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1892 aDocument, nTab, nEmptyCol );
1893 else if ( cDelim != 0 )
1894 rStream.WriteUniOrByteChar( cDelim );
1896 endlub( rStream );
1898 for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
1899 { // empty columns at beginning of row
1900 if ( bFixedWidth )
1901 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1902 aDocument, nTab, nEmptyCol );
1903 else if ( cDelim != 0 )
1904 rStream.WriteUniOrByteChar( cDelim );
1906 nNextRow = nRow;
1908 else if ( nNextCol < nCol )
1909 { // empty columns in same row
1910 for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
1911 { // columns in between
1912 if ( bFixedWidth )
1913 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1914 aDocument, nTab, nEmptyCol );
1915 else if ( cDelim != 0 )
1916 rStream.WriteUniOrByteChar( cDelim );
1919 if ( nCol == nEndCol )
1921 bProgress = true;
1922 nNextCol = nStartCol;
1923 nNextRow = nRow + 1;
1925 else
1926 nNextCol = nCol + 1;
1928 CellType eType = pCell->meType;
1929 ScAddress aPos(nCol, nRow, nTab);
1930 if ( bTabProtect )
1932 const ScProtectionAttr* pProtAttr =
1933 static_cast<const ScProtectionAttr*>( aDocument.GetAttr(
1934 nCol, nRow, nTab, ATTR_PROTECTION ));
1935 if ( pProtAttr->GetHideCell() ||
1936 ( eType == CELLTYPE_FORMULA && bShowFormulas &&
1937 pProtAttr->GetHideFormula() ) )
1938 eType = CELLTYPE_NONE; // hide
1940 bool bString;
1941 switch ( eType )
1943 case CELLTYPE_NONE:
1944 aString.clear();
1945 bString = false;
1946 break;
1947 case CELLTYPE_FORMULA :
1949 sal_uInt16 nErrCode;
1950 if ( bShowFormulas )
1952 pCell->mpFormula->GetFormula(aString);
1953 bString = true;
1955 else if ((nErrCode = pCell->mpFormula->GetErrCode()) != 0)
1957 aString = ScGlobal::GetErrorString( nErrCode );
1958 bString = true;
1960 else if (pCell->mpFormula->IsValue())
1962 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1963 if ( bFixedWidth || bSaveAsShown )
1965 Color* pDummy;
1966 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1967 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
1969 else
1971 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
1972 bString = false;
1975 else
1977 if ( bSaveAsShown )
1979 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1980 Color* pDummy;
1981 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1983 else
1984 aString = pCell->mpFormula->GetString().getString();
1985 bString = true;
1988 break;
1989 case CELLTYPE_STRING :
1990 if ( bSaveAsShown )
1992 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1993 Color* pDummy;
1994 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1996 else
1997 aString = pCell->mpString->getString();
1998 bString = true;
1999 break;
2000 case CELLTYPE_EDIT :
2002 const EditTextObject* pObj = pCell->mpEditText;
2003 EditEngine& rEngine = aDocument.GetEditEngine();
2004 rEngine.SetText( *pObj);
2005 aString = rEngine.GetText(); // including LF
2006 bString = true;
2008 break;
2009 case CELLTYPE_VALUE :
2011 sal_uInt32 nFormat;
2012 aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
2013 if ( bFixedWidth || bSaveAsShown )
2015 Color* pDummy;
2016 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2017 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
2019 else
2021 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
2022 bString = false;
2025 break;
2026 default:
2027 OSL_FAIL( "ScDocShell::AsciiSave: unknown CellType" );
2028 aString.clear();
2029 bString = false;
2032 if ( bFixedWidth )
2034 SvxCellHorJustify eHorJust = (SvxCellHorJustify)
2035 static_cast<const SvxHorJustifyItem*>( aDocument.GetAttr( nCol, nRow,
2036 nTab, ATTR_HOR_JUSTIFY ))->GetValue();
2037 lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
2038 !bString, eHorJust );
2039 rStream.WriteUnicodeOrByteText( aString );
2041 else
2043 OUString aUniString = aString;// TODO: remove that later
2044 if (!bString && cStrDelim != 0 && !aUniString.isEmpty())
2046 sal_Unicode c = aUniString[0];
2047 bString = (c == cStrDelim || c == ' ' ||
2048 aUniString.endsWith(" ") ||
2049 aUniString.indexOf(cStrDelim) >= 0);
2050 if (!bString && cDelim != 0)
2051 bString = (aUniString.indexOf(cDelim) >= 0);
2053 if ( bString )
2055 if ( cStrDelim != 0 ) //@ BugId 55355
2057 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
2059 bool bNeedQuotes = false;
2060 sal_Int32 nPos = getTextSepPos(
2061 aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes);
2063 escapeTextSep<OUString, OUStringBuffer>(
2064 nPos, OUString(cStrDelim), aUniString);
2066 if ( bNeedQuotes )
2067 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2068 write_uInt16s_FromOUString(rStream, aUniString);
2069 if ( bNeedQuotes )
2070 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2072 else
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.
2088 if ( bContextOrNotAsciiEncoding )
2090 // to byte encoding
2091 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2092 // back to Unicode
2093 OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
2095 // search on re-decoded string
2096 bool bNeedQuotes = false;
2097 sal_Int32 nPos = getTextSepPos(
2098 aStrDec, rAsciiOpt, aStrDelimDecoded, aDelimDecoded, bNeedQuotes);
2100 escapeTextSep<OUString, OUStringBuffer>(
2101 nPos, aStrDelimDecoded, aStrDec);
2103 // write byte re-encoded
2104 if ( bNeedQuotes )
2105 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2106 rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
2107 if ( bNeedQuotes )
2108 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2110 else
2112 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2114 // search on encoded string
2115 bool bNeedQuotes = false;
2116 sal_Int32 nPos = getTextSepPos(
2117 aStrEnc, rAsciiOpt, aStrDelimEncoded, aDelimEncoded, bNeedQuotes);
2119 escapeTextSep<OString, OStringBuffer>(
2120 nPos, aStrDelimEncoded, aStrEnc);
2122 // write byte encoded
2123 if ( bNeedQuotes )
2124 rStream.Write(
2125 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2126 rStream.Write(aStrEnc.getStr(), aStrEnc.getLength());
2127 if ( bNeedQuotes )
2128 rStream.Write(
2129 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2133 else
2134 rStream.WriteUnicodeOrByteText( aUniString );
2136 else
2137 rStream.WriteUnicodeOrByteText( aUniString );
2140 if( nCol < nEndCol )
2142 if(cDelim!=0) //@ BugId 55355
2143 rStream.WriteUniOrByteChar( cDelim );
2145 else
2146 endlub( rStream );
2148 if ( bProgress )
2149 aProgress.SetStateOnPercent( nRow );
2152 // write out empty if requested
2153 if ( nNextRow <= nEndRow )
2155 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
2156 { // remaining empty columns of last row
2157 if ( bFixedWidth )
2158 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2159 aDocument, nTab, nEmptyCol );
2160 else if ( cDelim != 0 )
2161 rStream.WriteUniOrByteChar( cDelim );
2163 endlub( rStream );
2164 nNextRow++;
2166 for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
2167 { // entire empty rows
2168 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
2170 if ( bFixedWidth )
2171 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2172 aDocument, nTab, nEmptyCol );
2173 else if ( cDelim != 0 )
2174 rStream.WriteUniOrByteChar( cDelim );
2176 endlub( rStream );
2179 rStream.SetStreamCharSet( eOldCharSet );
2180 rStream.SetEndian( nOldNumberFormatInt );
2183 bool ScDocShell::ConvertTo( SfxMedium &rMed )
2185 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
2187 // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
2188 // it's already in ExecuteSave (as for Save and SaveAs)
2190 if (pAutoStyleList)
2191 pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now
2192 if (GetCreateMode()== SfxObjectCreateMode::STANDARD)
2193 SfxObjectShell::SetVisArea( Rectangle() ); // Edited normally -> no VisArea
2195 OSL_ENSURE( rMed.GetFilter(), "Filter == 0" );
2197 bool bRet = false;
2198 OUString aFltName = rMed.GetFilter()->GetFilterName();
2200 if (aFltName == pFilterXML)
2202 //TODO/LATER: this shouldn't happen!
2203 OSL_FAIL("XML filter in ConvertFrom?!");
2204 bRet = SaveXML( &rMed, NULL );
2206 else if (aFltName == pFilterExcel5 || aFltName == pFilterExcel95 ||
2207 aFltName == pFilterExcel97 || aFltName == pFilterEx5Temp ||
2208 aFltName == pFilterEx95Temp || aFltName == pFilterEx97Temp)
2210 WaitObject aWait( GetActiveDialogParent() );
2212 bool bDoSave = true;
2213 if( ScTabViewShell* pViewShell = GetBestViewShell() )
2215 ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
2216 if( !pExtDocOpt )
2217 aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
2218 pViewShell->GetViewData().WriteExtOptions( *pExtDocOpt );
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 if( (rMed.GetFilter()->GetFilterFlags() & SfxFilterFlags::ENCRYPTION) == SfxFilterFlags::NONE )
2225 SfxItemSet* pItemSet = rMed.GetItemSet();
2226 const SfxPoolItem* pItem = 0;
2227 if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, true, &pItem ) == SfxItemState::SET )
2229 bDoSave = ScWarnPassword::WarningOnPassword( rMed );
2230 // #i42858# remove password from medium (warn only one time)
2231 if( bDoSave )
2232 pItemSet->ClearItem( SID_PASSWORD );
2236 if( bDoSave )
2238 bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
2239 bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
2243 if( bDoSave )
2245 ExportFormatExcel eFormat = ExpBiff5;
2246 if( aFltName == pFilterExcel97 || aFltName == pFilterEx97Temp )
2247 eFormat = ExpBiff8;
2248 FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
2250 if( eError && !GetError() )
2251 SetError( eError, OUString( OSL_LOG_PREFIX ) );
2253 // don't return false for warnings
2254 bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
2256 else
2258 // export aborted, i.e. "Save without password" warning
2259 SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
2262 else if (aFltName == pFilterAscii)
2264 SvStream* pStream = rMed.GetOutStream();
2265 if (pStream)
2267 OUString sItStr;
2268 SfxItemSet* pSet = rMed.GetItemSet();
2269 const SfxPoolItem* pItem;
2270 if ( pSet && SfxItemState::SET ==
2271 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2273 sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
2276 if ( sItStr.isEmpty() )
2278 // default for ascii export (from API without options):
2279 // ISO8859-1/MS_1252 encoding, comma, double quotes
2281 ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
2282 sItStr = aDefOptions.BuildString();
2285 WaitObject aWait( GetActiveDialogParent() );
2286 ScImportOptions aOptions( sItStr );
2287 AsciiSave( *pStream, aOptions );
2288 bRet = true;
2290 if (aDocument.GetTableCount() > 1)
2291 if (!rMed.GetError())
2292 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2295 else if (aFltName == pFilterDBase)
2297 OUString sCharSet;
2298 SfxItemSet* pSet = rMed.GetItemSet();
2299 const SfxPoolItem* pItem;
2300 if ( pSet && SfxItemState::SET ==
2301 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2303 sCharSet = static_cast<const SfxStringItem*>(pItem)->GetValue();
2306 if (sCharSet.isEmpty())
2308 // default for dBase export (from API without options):
2309 // IBM_850 encoding
2311 sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
2314 WaitObject aWait( GetActiveDialogParent() );
2315 // FIXME: Hack so that the Sba opened TempFile can be overwritten
2316 rMed.CloseOutStream();
2317 bool bHasMemo = false;
2319 sal_uLong eError = DBaseExport(
2320 rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo);
2322 if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
2324 eError = eERR_OK;
2327 INetURLObject aTmpFile( rMed.GetPhysicalName(), INetProtocol::File );
2328 if ( bHasMemo )
2329 aTmpFile.setExtension(OUString("dbt"));
2330 if ( eError != eERR_OK )
2332 if (!GetError())
2333 SetError(eError, OUString( OSL_LOG_PREFIX ));
2334 if ( bHasMemo && IsDocument( aTmpFile ) )
2335 KillFile( aTmpFile );
2337 else
2339 bRet = true;
2340 if ( bHasMemo )
2342 const SfxStringItem* pNameItem =
2343 static_cast<const SfxStringItem*>( rMed.GetItemSet()->GetItem( SID_FILE_NAME ) );
2344 INetURLObject aDbtFile( pNameItem->GetValue(), INetProtocol::File );
2345 aDbtFile.setExtension(OUString("dbt"));
2346 if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
2347 bRet = false;
2348 if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
2349 bRet = false;
2350 if ( !bRet )
2352 KillFile( aTmpFile );
2353 if ( !GetError() )
2354 SetError( SCERR_EXPORT_DATA, OUString( OSL_LOG_PREFIX ) );
2359 else if (aFltName == pFilterDif)
2361 SvStream* pStream = rMed.GetOutStream();
2362 if (pStream)
2364 OUString sItStr;
2365 SfxItemSet* pSet = rMed.GetItemSet();
2366 const SfxPoolItem* pItem;
2367 if ( pSet && SfxItemState::SET ==
2368 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2370 sItStr = static_cast<const SfxStringItem*>(pItem)->GetValue();
2373 if (sItStr.isEmpty())
2375 // default for DIF export (from API without options):
2376 // ISO8859-1/MS_1252 encoding
2378 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
2381 WaitObject aWait( GetActiveDialogParent() );
2382 ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
2383 ScGlobal::GetCharsetValue(sItStr) );
2384 bRet = true;
2386 if (aDocument.GetTableCount() > 1)
2387 if (!rMed.GetError())
2388 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2391 else if (aFltName == pFilterSylk)
2393 SvStream* pStream = rMed.GetOutStream();
2394 if ( pStream )
2396 WaitObject aWait( GetActiveDialogParent() );
2398 SCCOL nEndCol;
2399 SCROW nEndRow;
2400 aDocument.GetCellArea( 0, nEndCol, nEndRow );
2401 ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
2403 ScImportExport aImExport( &aDocument, aRange );
2404 aImExport.SetFormulas( true );
2405 bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SotClipboardFormatId::SYLK );
2408 else if (aFltName == pFilterHtml)
2410 SvStream* pStream = rMed.GetOutStream();
2411 if ( pStream )
2413 SfxItemSet* pSet = rMed.GetItemSet();
2414 const SfxPoolItem* pItem;
2415 OUString sFilterOptions;
2417 if (pSet->GetItemState(SID_FILE_FILTEROPTIONS, true, &pItem) == SfxItemState::SET)
2418 sFilterOptions = static_cast<const SfxStringItem*>(pItem)->GetValue();
2420 WaitObject aWait(GetActiveDialogParent());
2421 ScImportExport aImExport(&aDocument);
2422 aImExport.SetStreamPath(rMed.GetName());
2423 aImExport.SetFilterOptions(sFilterOptions);
2424 bRet = aImExport.ExportStream(*pStream, rMed.GetBaseURL(true), SotClipboardFormatId::HTML);
2425 if (bRet && !aImExport.GetNonConvertibleChars().isEmpty())
2427 SetError(*new StringErrorInfo(
2428 SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
2429 aImExport.GetNonConvertibleChars(),
2430 ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO), OUString(OSL_LOG_PREFIX));
2434 else
2436 if (GetError())
2437 SetError(SCERR_IMPORT_NI, OUString(OSL_LOG_PREFIX));
2439 return bRet;
2442 bool ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
2444 return SfxObjectShell::SaveCompleted( xStor );
2447 bool ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
2449 bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
2451 // SC_HINT_DOC_SAVED for change ReadOnly -> Read/Write
2452 Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
2453 return bRet;
2456 bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId )
2458 // #i112634# ask VBA event handlers whether to save or print the document
2460 using namespace ::com::sun::star::script::vba;
2462 sal_Int32 nVbaEventId = VBAEventId::NO_EVENT;
2463 uno::Sequence< uno::Any > aArgs;
2464 switch( nSlotId )
2466 case SID_SAVEDOC:
2467 case SID_SAVEASDOC:
2468 nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE;
2469 aArgs.realloc( 1 );
2470 aArgs[ 0 ] <<= (nSlotId == SID_SAVEASDOC);
2471 break;
2472 case SID_PRINTDOC:
2473 case SID_PRINTDOCDIRECT:
2474 nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT;
2475 break;
2478 bool bSlotExecutable = true;
2479 if( nVbaEventId != VBAEventId::NO_EVENT ) try
2481 uno::Reference< XVBAEventProcessor > xEventProcessor( aDocument.GetVbaEventProcessor(), uno::UNO_QUERY_THROW );
2482 xEventProcessor->processVbaEvent( nVbaEventId, aArgs );
2484 catch( util::VetoException& )
2486 bSlotExecutable = false;
2488 catch( uno::Exception& )
2491 return bSlotExecutable;
2494 bool ScDocShell::PrepareClose( bool bUI )
2496 if(SC_MOD()->GetCurRefDlgId()>0)
2498 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
2499 if( pFrame )
2501 SfxViewShell* p = pFrame->GetViewShell();
2502 ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
2503 if(pViewSh!=NULL)
2505 vcl::Window *pWin=pViewSh->GetWindow();
2506 if(pWin!=NULL) pWin->GrabFocus();
2510 return false;
2512 if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
2514 ErrorMessage(STR_CLOSE_ERROR_LINK);
2515 return false;
2518 DoEnterHandler();
2520 // start 'Workbook_BeforeClose' VBA event handler for possible veto
2521 if( !IsInPrepareClose() )
2525 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( aDocument.GetVbaEventProcessor(), uno::UNO_SET_THROW );
2526 uno::Sequence< uno::Any > aArgs;
2527 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs );
2529 catch( util::VetoException& )
2531 // if event processor throws VetoException, macro has vetoed close
2532 return false;
2534 catch( uno::Exception& )
2538 // end handler code
2540 bool nRet = SfxObjectShell::PrepareClose( bUI );
2541 if (nRet) // true == close
2542 aDocument.EnableIdle(false); // Do not mess around with it anymore!
2544 return nRet;
2547 void ScDocShell::PrepareReload()
2549 SfxObjectShell::PrepareReload(); // FIXME: Doesn't do a thing?
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.
2556 // Thus: Disconnect the DDE Links of the old Document before Reload
2557 aDocument.GetDocLinkManager().disconnectDdeLinks();
2560 OUString ScDocShell::GetOwnFilterName()
2562 return OUString(pFilterSc50);
2565 OUString ScDocShell::GetHtmlFilterName()
2567 return OUString(pFilterHtml);
2570 OUString ScDocShell::GetWebQueryFilterName()
2572 return OUString(pFilterHtmlWebQ);
2575 OUString ScDocShell::GetAsciiFilterName()
2577 return OUString(pFilterAscii);
2580 OUString ScDocShell::GetLotusFilterName()
2582 return OUString(pFilterLotus);
2585 OUString ScDocShell::GetDBaseFilterName()
2587 return OUString(pFilterDBase);
2590 OUString ScDocShell::GetDifFilterName()
2592 return OUString(pFilterDif);
2595 bool ScDocShell::HasAutomaticTableName( const OUString& rFilter )
2597 // sal_True for those filters that keep the default table name
2598 // (which is language specific)
2600 return rFilter == pFilterAscii
2601 || rFilter == pFilterLotus
2602 || rFilter == pFilterExcel4
2603 || rFilter == pFilterEx4Temp
2604 || rFilter == pFilterDBase
2605 || rFilter == pFilterDif
2606 || rFilter == pFilterSylk
2607 || rFilter == pFilterHtml
2608 || rFilter == pFilterRtf;
2611 #if ! ENABLE_TELEPATHY
2612 ScDocFunc *ScDocShell::CreateDocFunc()
2614 return new ScDocFuncDirect( *this );
2616 #else
2617 ScCollaboration* ScDocShell::GetCollaboration()
2619 return mpCollaboration;
2621 #endif
2623 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 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 pModificator ( NULL )
2647 #if ENABLE_TELEPATHY
2648 , mpCollaboration( new ScCollaboration( this ) )
2649 #endif
2651 SetPool( &SC_MOD()->GetPool() );
2653 bIsInplace = rShell.bIsInplace;
2655 pDocFunc = CreateDocFunc();
2657 // SetBaseModel needs exception handling
2658 ScModelObj::CreateAndSet( this );
2660 StartListening(*this);
2661 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2662 if (pStlPool)
2663 StartListening(*pStlPool);
2665 GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
2666 SetHelpId( HID_SCSHELL_DOCSH );
2668 // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2671 ScDocShell::ScDocShell( const SfxModelFlags i_nSfxCreationFlags ) :
2672 SfxObjectShell( i_nSfxCreationFlags ),
2673 aDocument ( SCDOCMODE_DOCUMENT, this ),
2674 aDdeTextFmt(OUString("TEXT")),
2675 nPrtToScreenFactor( 1.0 ),
2676 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 pModificator ( NULL )
2692 #if ENABLE_TELEPATHY
2693 , mpCollaboration( new ScCollaboration( this ) )
2694 #endif
2696 SetPool( &SC_MOD()->GetPool() );
2698 bIsInplace = (GetCreateMode() == SfxObjectCreateMode::EMBEDDED);
2699 // Will be reset if not in place
2701 pDocFunc = CreateDocFunc();
2703 // SetBaseModel needs exception handling
2704 ScModelObj::CreateAndSet( this );
2706 StartListening(*this);
2707 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2708 if (pStlPool)
2709 StartListening(*pStlPool);
2710 SetHelpId( HID_SCSHELL_DOCSH );
2712 aDocument.GetDBCollection()->SetRefreshHandler(
2713 LINK( this, ScDocShell, RefreshDBDataHdl ) );
2715 // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2718 ScDocShell::~ScDocShell()
2720 ResetDrawObjectShell(); // If the Drawing Layer still tries to access it, access it
2722 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2723 if (pStlPool)
2724 EndListening(*pStlPool);
2725 EndListening(*this);
2727 delete pAutoStyleList;
2729 SfxApplication *pSfxApp = SfxGetpApp();
2730 if ( pSfxApp->GetDdeService() ) // Delete DDE for Document
2731 pSfxApp->RemoveDdeTopic( this );
2733 delete pDocFunc;
2734 delete aDocument.mpUndoManager;
2735 aDocument.mpUndoManager = 0;
2736 delete pImpl;
2738 delete pPaintLockData;
2740 delete pSolverSaveData;
2741 delete pSheetSaveData;
2742 delete pOldAutoDBRange;
2744 if (pModificator)
2746 OSL_FAIL("The Modificator should not exist");
2747 delete pModificator;
2749 #if ENABLE_TELEPATHY
2750 delete mpCollaboration;
2751 #endif
2754 ::svl::IUndoManager* ScDocShell::GetUndoManager()
2756 return aDocument.GetUndoManager();
2759 void ScDocShell::SetModified( bool bModified )
2761 if ( SfxObjectShell::IsEnableSetModified() )
2763 SfxObjectShell::SetModified( bModified );
2764 Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
2768 void ScDocShell::SetDocumentModified( bool bIsModified /* = true */ )
2770 // BroadcastUno must also happen right away with pPaintLockData
2771 // FIXME: Also for SetDrawModified, if Drawing is connected
2772 // FIXME: Then own Hint?
2774 if ( pPaintLockData && bIsModified )
2776 // #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results
2777 // of RecalcModeAlways formulas (like OFFSET) after modifying cells
2778 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2779 aDocument.InvalidateTableArea(); // #i105279# needed here
2780 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2782 pPaintLockData->SetModified(); // Later on ...
2783 return;
2786 SetDrawModified( bIsModified );
2788 if ( bIsModified )
2790 if ( aDocument.IsAutoCalcShellDisabled() )
2791 SetDocumentModifiedPending( true );
2792 else
2794 SetDocumentModifiedPending( false );
2795 aDocument.InvalidateStyleSheetUsage();
2796 aDocument.InvalidateTableArea();
2797 aDocument.InvalidateLastTableOpParams();
2798 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2799 if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
2800 aDocument.CalcFormulaTree( true );
2801 PostDataChanged();
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).
2808 ScDetOpList* pList = aDocument.GetDetOpList();
2809 if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
2810 pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
2812 GetDocFunc().DetectiveRefresh(true); // sal_True = caused by automatic update
2814 aDocument.SetDetectiveDirty(false); // always reset, also if not refreshed
2817 // notify UNO objects after BCA_BRDCST_ALWAYS etc.
2818 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2823 * SetDrawModified - without Formula update
2825 * Drawing also needs to be updated for the normal SetDocumentModified
2826 * e.g.: when deleting tables etc.
2828 void ScDocShell::SetDrawModified( bool bIsModified /* = true */ )
2830 bool bUpdate = bIsModified != IsModified();
2832 SetModified( bIsModified );
2834 SfxBindings* pBindings = GetViewBindings();
2835 if (bUpdate)
2837 if (pBindings)
2839 pBindings->Invalidate( SID_SAVEDOC );
2840 pBindings->Invalidate( SID_DOC_MODIFIED );
2844 if (bIsModified)
2846 if (pBindings)
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 pBindings->Invalidate( SID_UNDO );
2852 pBindings->Invalidate( SID_REDO );
2853 pBindings->Invalidate( SID_REPEAT );
2856 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
2858 aDocument.UpdateChartListenerCollection();
2859 SfxGetpApp()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
2861 SC_MOD()->AnythingChanged();
2865 void ScDocShell::SetInUndo(bool bSet)
2867 bIsInUndo = bSet;
2870 void ScDocShell::GetDocStat( ScDocStat& rDocStat )
2872 SfxPrinter* pPrinter = GetPrinter();
2874 aDocument.GetDocStat( rDocStat );
2875 rDocStat.nPageCount = 0;
2877 if ( pPrinter )
2878 for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
2879 rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount +
2880 (sal_uInt16) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
2883 VclPtr<SfxDocumentInfoDialog> ScDocShell::CreateDocumentInfoDialog(
2884 vcl::Window *pParent, const SfxItemSet &rSet )
2886 VclPtr<SfxDocumentInfoDialog> pDlg = VclPtr<SfxDocumentInfoDialog>::Create( pParent, rSet );
2887 ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
2889 // Only for statistics, if this Doc is shown; not from the Doc Manager
2890 if( pDocSh == this )
2892 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
2893 OSL_ENSURE(pFact, "ScAbstractFactory create fail!");
2894 ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
2895 OSL_ENSURE(ScDocStatPageCreate, "Tabpage create fail!");
2896 pDlg->AddFontTabPage();
2897 pDlg->AddTabPage( 42,
2898 ScGlobal::GetRscString( STR_DOC_STAT ),
2899 ScDocStatPageCreate,
2900 NULL);
2902 return pDlg;
2905 vcl::Window* ScDocShell::GetActiveDialogParent()
2907 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2908 if ( pViewSh )
2909 return pViewSh->GetDialogParent();
2910 else
2911 return Application::GetDefDialogParent();
2914 void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
2916 delete pSolverSaveData;
2917 pSolverSaveData = new ScOptSolverSave( rData );
2920 ScSheetSaveData* ScDocShell::GetSheetSaveData()
2922 if (!pSheetSaveData)
2923 pSheetSaveData = new ScSheetSaveData;
2925 return pSheetSaveData;
2928 namespace {
2930 void removeKeysIfExists(Reference<ui::XAcceleratorConfiguration>& xScAccel, const vector<const awt::KeyEvent*>& rKeys)
2932 vector<const awt::KeyEvent*>::const_iterator itr = rKeys.begin(), itrEnd = rKeys.end();
2933 for (; itr != itrEnd; ++itr)
2935 const awt::KeyEvent* p = *itr;
2936 if (!p)
2937 continue;
2941 xScAccel->removeKeyEvent(*p);
2943 catch (const container::NoSuchElementException&) {}
2949 void ScDocShell::ResetKeyBindings( ScOptionsUtil::KeyBindingType eType )
2951 using namespace ::com::sun::star::ui;
2953 Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2954 if (!xContext.is())
2955 return;
2957 Reference<XModuleUIConfigurationManagerSupplier> xModuleCfgSupplier(
2958 theModuleUIConfigurationManagerSupplier::get(xContext) );
2960 // Grab the Calc configuration.
2961 Reference<XUIConfigurationManager> xConfigMgr =
2962 xModuleCfgSupplier->getUIConfigurationManager(
2963 OUString("com.sun.star.sheet.SpreadsheetDocument"));
2965 if (!xConfigMgr.is())
2966 return;
2968 // shortcut manager
2969 Reference<XAcceleratorConfiguration> xScAccel = xConfigMgr->getShortCutManager();
2971 if (!xScAccel.is())
2972 return;
2974 vector<const awt::KeyEvent*> aKeys;
2975 aKeys.reserve(4);
2977 // Backsapce key
2978 awt::KeyEvent aBackspace;
2979 aBackspace.KeyCode = awt::Key::BACKSPACE;
2980 aBackspace.Modifiers = 0;
2981 aKeys.push_back(&aBackspace);
2983 // Delete key
2984 awt::KeyEvent aDelete;
2985 aDelete.KeyCode = awt::Key::DELETE;
2986 aDelete.Modifiers = 0;
2987 aKeys.push_back(&aDelete);
2989 // Ctrl-D
2990 awt::KeyEvent aCtrlD;
2991 aCtrlD.KeyCode = awt::Key::D;
2992 aCtrlD.Modifiers = awt::KeyModifier::MOD1;
2993 aKeys.push_back(&aCtrlD);
2995 // Alt-Down
2996 awt::KeyEvent aAltDown;
2997 aAltDown.KeyCode = awt::Key::DOWN;
2998 aAltDown.Modifiers = awt::KeyModifier::MOD2;
2999 aKeys.push_back(&aAltDown);
3001 // Remove all involved keys first, because swapping commands don't work
3002 // well without doing this.
3003 removeKeysIfExists(xScAccel, aKeys);
3004 xScAccel->store();
3006 switch (eType)
3008 case ScOptionsUtil::KEY_DEFAULT:
3009 xScAccel->setKeyEvent(aDelete, OUString(".uno:ClearContents"));
3010 xScAccel->setKeyEvent(aBackspace, OUString(".uno:Delete"));
3011 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:FillDown"));
3012 xScAccel->setKeyEvent(aAltDown, OUString(".uno:DataSelect"));
3013 break;
3014 case ScOptionsUtil::KEY_OOO_LEGACY:
3015 xScAccel->setKeyEvent(aDelete, OUString(".uno:Delete"));
3016 xScAccel->setKeyEvent(aBackspace, OUString(".uno:ClearContents"));
3017 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:DataSelect"));
3018 break;
3019 default:
3023 xScAccel->store();
3026 void ScDocShell::UseSheetSaveEntries()
3028 if (pSheetSaveData)
3030 pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
3032 bool bHasEntries = false;
3033 SCTAB nTabCount = aDocument.GetTableCount();
3034 SCTAB nTab;
3035 for (nTab = 0; nTab < nTabCount; ++nTab)
3036 if (pSheetSaveData->HasStreamPos(nTab))
3037 bHasEntries = true;
3039 if (!bHasEntries)
3041 // if no positions were set (for example, export to other format),
3042 // reset all "valid" flags
3044 for (nTab = 0; nTab < nTabCount; ++nTab)
3045 if (aDocument.IsStreamValid(nTab))
3046 aDocument.SetStreamValid(nTab, false);
3051 // --- ScDocShellModificator ------------------------------------------
3053 ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
3055 rDocShell( rDS ),
3056 mpProtector(new ScRefreshTimerProtector(rDS.GetDocument().GetRefreshTimerControlAddress()))
3058 ScDocument& rDoc = rDocShell.GetDocument();
3059 bAutoCalcShellDisabled = rDoc.IsAutoCalcShellDisabled();
3060 bIdleEnabled = rDoc.IsIdleEnabled();
3061 rDoc.SetAutoCalcShellDisabled( true );
3062 rDoc.EnableIdle(false);
3065 ScDocShellModificator::~ScDocShellModificator()
3067 ScDocument& rDoc = rDocShell.GetDocument();
3068 rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3069 if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
3070 rDocShell.SetDocumentModified(); // last one shuts off the lights
3071 rDoc.EnableIdle(bIdleEnabled);
3074 void ScDocShellModificator::SetDocumentModified()
3076 ScDocument& rDoc = rDocShell.GetDocument();
3077 rDoc.ClearFormulaContext();
3078 if ( !rDoc.IsImportingXML() )
3080 // AutoCalcShellDisabled temporaer restaurieren
3081 bool bDisabled = rDoc.IsAutoCalcShellDisabled();
3082 rDoc.SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3083 rDocShell.SetDocumentModified();
3084 rDoc.SetAutoCalcShellDisabled( bDisabled );
3086 else
3088 // uno broadcast is necessary for api to work
3089 // -> must also be done during xml import
3090 rDoc.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
3094 bool ScDocShell::IsChangeRecording() const
3096 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3097 return pChangeTrack != NULL;
3100 bool ScDocShell::HasChangeRecordProtection() const
3102 bool bRes = false;
3103 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3104 if (pChangeTrack)
3105 bRes = pChangeTrack->IsProtected();
3106 return bRes;
3109 void ScDocShell::SetChangeRecording( bool bActivate )
3111 bool bOldChangeRecording = IsChangeRecording();
3113 if (bActivate)
3115 aDocument.StartChangeTracking();
3116 ScChangeViewSettings aChangeViewSet;
3117 aChangeViewSet.SetShowChanges(true);
3118 aDocument.SetChangeViewSettings(aChangeViewSet);
3120 else
3122 aDocument.EndChangeTracking();
3123 PostPaintGridAll();
3126 if (bOldChangeRecording != IsChangeRecording())
3128 UpdateAcceptChangesDialog();
3129 // Slots invalidieren
3130 SfxBindings* pBindings = GetViewBindings();
3131 if (pBindings)
3132 pBindings->InvalidateAll(false);
3136 bool ScDocShell::SetProtectionPassword( const OUString &rNewPassword )
3138 bool bRes = false;
3139 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3140 if (pChangeTrack)
3142 bool bProtected = pChangeTrack->IsProtected();
3144 if (!rNewPassword.isEmpty())
3146 // when password protection is applied change tracking must always be active
3147 SetChangeRecording( true );
3149 ::com::sun::star::uno::Sequence< sal_Int8 > aProtectionHash;
3150 SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword );
3151 pChangeTrack->SetProtection( aProtectionHash );
3153 else
3155 pChangeTrack->SetProtection( ::com::sun::star::uno::Sequence< sal_Int8 >() );
3157 bRes = true;
3159 if ( bProtected != pChangeTrack->IsProtected() )
3161 UpdateAcceptChangesDialog();
3162 SetDocumentModified();
3166 return bRes;
3169 bool ScDocShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > &rPasswordHash )
3171 bool bRes = false;
3172 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3173 if (pChangeTrack && pChangeTrack->IsProtected())
3175 rPasswordHash = pChangeTrack->GetProtection();
3176 bRes = true;
3178 return bRes;
3181 void ScDocShell::libreOfficeKitCallback(int nType, const char* pPayload) const
3183 aDocument.GetDrawLayer()->libreOfficeKitCallback(nType, pPayload);
3186 bool ScDocShell::isTiledRendering() const
3188 return aDocument.GetDrawLayer() && aDocument.GetDrawLayer()->isTiledRendering();
3191 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */