Bump version to 4.3-4
[LibreOffice.git] / sc / source / ui / docshell / docsh.cxx
blobd44d49f64879c92bc233575ed4e1b95ae4ccfd8a
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 pFilterSc40[] = "StarCalc 4.0";
148 static const sal_Char pFilterSc30[] = "StarCalc 3.0";
149 static const sal_Char pFilterSc10[] = "StarCalc 1.0";
150 static const sal_Char pFilterXML[] = "StarOffice XML (Calc)";
151 static const sal_Char pFilterAscii[] = "Text - txt - csv (StarCalc)";
152 static const sal_Char pFilterLotus[] = "Lotus";
153 static const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
154 static const sal_Char pFilterExcel4[] = "MS Excel 4.0";
155 static const sal_Char pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
156 static const sal_Char pFilterExcel5[] = "MS Excel 5.0/95";
157 static const sal_Char pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
158 static const sal_Char pFilterExcel95[] = "MS Excel 95";
159 static const sal_Char pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
160 static const sal_Char pFilterExcel97[] = "MS Excel 97";
161 static const sal_Char pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
162 static const sal_Char pFilterDBase[] = "dBase";
163 static const sal_Char pFilterDif[] = "DIF";
164 static const sal_Char pFilterSylk[] = "SYLK";
165 static const sal_Char pFilterHtml[] = "HTML (StarCalc)";
166 static const sal_Char pFilterHtmlWebQ[] = "calc_HTML_WebQuery";
167 static const sal_Char pFilterRtf[] = "Rich Text Format (StarCalc)";
169 #define ScDocShell
170 #include "scslots.hxx"
173 SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell, ScResId(SCSTR_DOCSHELL))
175 void ScDocShell::InitInterface_Impl()
179 // GlobalName of the current version:
180 SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "scalc" )
182 TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: No TypeInfo?
184 void ScDocShell::FillClass( SvGlobalName* pClassName,
185 sal_uInt32* pFormat,
186 OUString* /* pAppName */,
187 OUString* pFullTypeName,
188 OUString* pShortTypeName,
189 sal_Int32 nFileFormat,
190 bool bTemplate /* = false */) const
192 if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
194 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
195 *pFormat = SOT_FORMATSTR_ID_STARCALC_60;
196 *pFullTypeName = OUString( ScResId( SCSTR_LONG_SCDOC_NAME ) );
197 *pShortTypeName = OUString( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
199 else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
201 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
202 *pFormat = bTemplate ? SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : SOT_FORMATSTR_ID_STARCALC_8;
203 *pFullTypeName = "calc8";
204 *pShortTypeName = ScResId(SCSTR_SHORT_SCDOC_NAME).toString();
206 else
208 OSL_FAIL("Which version?");
212 void ScDocShell::DoEnterHandler()
214 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
215 if (pViewSh)
216 if (pViewSh->GetViewData()->GetDocShell() == this)
217 SC_MOD()->InputEnterHandler();
220 SCTAB ScDocShell::GetSaveTab()
222 SCTAB nTab = 0;
223 ScTabViewShell* pSh = GetBestViewShell();
224 if (pSh)
226 const ScMarkData& rMark = pSh->GetViewData()->GetMarkData();
227 nTab = rMark.GetFirstSelected();
229 return nTab;
232 sal_uInt16 ScDocShell::GetHiddenInformationState( sal_uInt16 nStates )
234 // get global state like HIDDENINFORMATION_DOCUMENTVERSIONS
235 sal_uInt16 nState = SfxObjectShell::GetHiddenInformationState( nStates );
237 if ( nStates & HIDDENINFORMATION_RECORDEDCHANGES )
239 if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
240 nState |= HIDDENINFORMATION_RECORDEDCHANGES;
242 if ( nStates & HIDDENINFORMATION_NOTES )
244 SCTAB nTableCount = aDocument.GetTableCount();
245 bool bFound = false;
246 for (SCTAB nTab = 0; nTab < nTableCount && !bFound; ++nTab)
248 if (aDocument.HasTabNotes(nTab)) //TODO:
249 bFound = true;
252 if (bFound)
253 nState |= HIDDENINFORMATION_NOTES;
256 return nState;
259 void ScDocShell::BeforeXMLLoading()
261 aDocument.EnableIdle(false);
263 // prevent unnecessary broadcasts and updates
264 OSL_ENSURE(pModificator == NULL, "The Modificator should not exist");
265 pModificator = new ScDocShellModificator( *this );
267 aDocument.SetImportingXML( true );
268 aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
269 aDocument.EnableUndo( false );
270 // prevent unnecessary broadcasts and "half way listeners"
271 aDocument.SetInsertingFromOtherDoc( true );
274 void ScDocShell::AfterXMLLoading(bool bRet)
276 if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
278 UpdateLinks();
279 // don't prevent establishing of listeners anymore
280 aDocument.SetInsertingFromOtherDoc( false );
281 if ( bRet )
283 ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
284 if (pChartListener)
285 pChartListener->UpdateDirtyCharts();
287 // #95582#; set the table names of linked tables to the new path
288 SCTAB nTabCount = aDocument.GetTableCount();
289 for (SCTAB i = 0; i < nTabCount; ++i)
291 if (aDocument.IsLinked( i ))
293 OUString aName;
294 aDocument.GetName(i, aName);
295 OUString aLinkTabName = aDocument.GetLinkTab(i);
296 sal_Int32 nLinkTabNameLength = aLinkTabName.getLength();
297 sal_Int32 nNameLength = aName.getLength();
298 if (nLinkTabNameLength < nNameLength)
301 // remove the quottes on begin and end of the docname and restore the escaped quotes
302 const sal_Unicode* pNameBuffer = aName.getStr();
303 if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
304 ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
306 OUStringBuffer aDocURLBuffer;
307 bool bQuote = true; // Document name is always quoted
308 ++pNameBuffer;
309 while ( bQuote && *pNameBuffer )
311 if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
312 bQuote = false;
313 else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
314 aDocURLBuffer.append(*pNameBuffer); // If escaped quote: only quote in the name
315 ++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() == SFX_CREATE_MODE_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 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 boost::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() != SFX_CREATE_MODE_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( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
599 return bRet;
602 void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
604 if (rHint.ISA(ScTablesHint) )
606 const ScTablesHint& rScHint = static_cast< const ScTablesHint& >( rHint );
607 if (rScHint.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] <<= rScHint.GetTab1();
614 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs );
616 catch( uno::Exception& )
622 if (rHint.ISA(SfxSimpleHint)) // Without parameter
624 sal_uLong nSlot = ((const SfxSimpleHint&)rHint).GetId();
625 switch ( nSlot )
627 case SFX_HINT_TITLECHANGED:
628 aDocument.SetName( SfxShell::GetName() );
629 // RegisterNewTargetNames gibts nicht mehr
630 SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
631 break;
634 else if (rHint.ISA(SfxStyleSheetHint)) // Template changed
635 NotifyStyle((const SfxStyleSheetHint&) rHint);
636 else if (rHint.ISA(ScAutoStyleHint))
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 ScAutoStyleHint& rStlHint = (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 ( rHint.ISA( SfxEventHint ) )
656 sal_uLong nEventId = ((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 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 uno::Sequence< OUString > aData = aLockFile.GetLockData();
797 if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
799 if ( !aData[LOCKFILE_OOOUSERNAME_ID].isEmpty() )
801 aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
803 else if ( !aData[LOCKFILE_SYSUSERNAME_ID].isEmpty() )
805 aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
809 catch ( uno::Exception& )
811 bNoLockAccess = true;
814 if ( bNoLockAccess )
816 // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
817 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
819 else
821 OUString aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
822 aMessage = aMessage.replaceFirst( "%1", aUserName );
824 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
825 if ( aBox.Execute() == RET_RETRY )
827 bRetry = true;
831 else
833 // merge changes from shared file into temp file
834 bool bSaveToShared = false;
835 if ( pSharedDocShell )
837 bSaveToShared = MergeSharedDocument( pSharedDocShell );
840 // close shared file
841 xCloseable->close( sal_True );
843 // TODO: keep file lock on shared file
845 // store to shared file
846 if ( bSaveToShared )
848 bool bChangedViewSettings = false;
849 ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
850 if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
852 pChangeViewSet->SetShowChanges( false );
853 pChangeViewSet->SetShowAccepted( false );
854 aDocument.SetChangeViewSettings( *pChangeViewSet );
855 bChangedViewSettings = true;
858 uno::Reference< frame::XStorable > xStor( GetModel(), uno::UNO_QUERY_THROW );
859 // TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
860 uno::Sequence< beans::PropertyValue > aValues(1);
861 aValues[0].Name = "FilterName";
862 aValues[0].Value <<= OUString( GetMedium()->GetFilter()->GetFilterName() );
864 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, false);
865 if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
867 aValues.realloc( 2 );
868 aValues[1].Name = "Password";
869 aValues[1].Value <<= pPasswordItem->GetValue();
872 SC_MOD()->SetInSharedDocSaving( true );
873 xStor->storeToURL( GetSharedFileURL(), aValues );
874 SC_MOD()->SetInSharedDocSaving( false );
876 if ( bChangedViewSettings )
878 pChangeViewSet->SetShowChanges( true );
879 pChangeViewSet->SetShowAccepted( true );
880 aDocument.SetChangeViewSettings( *pChangeViewSet );
884 bSuccess = true;
885 GetUndoManager()->Clear();
888 else
890 xCloseable->close( sal_True );
892 if ( bEntriesNotAccessible )
894 // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
895 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
897 else
899 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
900 ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
901 aBox.Execute();
903 SfxBindings* pBindings = GetViewBindings();
904 if ( pBindings )
906 pBindings->ExecuteSynchron( SID_SAVEASDOC );
911 catch ( uno::Exception& )
913 OSL_FAIL( "SFX_EVENT_SAVEDOC: caught exception\n" );
914 SC_MOD()->SetInSharedDocSaving( false );
918 uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
919 xClose->close( sal_True );
921 catch ( uno::Exception& )
927 if ( !bSuccess )
928 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
930 #endif
932 if (pSheetSaveData)
933 pSheetSaveData->SetInSupportedSave(true);
935 break;
936 case SFX_EVENT_SAVEASDOC:
938 if ( GetDocument()->GetExternalRefManager()->containsUnsavedReferences() )
940 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
941 ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
943 if( RET_NO == aBox.Execute())
945 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
948 } // fall through
949 case SFX_EVENT_SAVETODOC:
950 // #i108978# If no event is sent before saving, there will also be no "...DONE" event,
951 // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
952 // if there is a SAVE/SAVEAS/SAVETO event first.
953 if (pSheetSaveData)
954 pSheetSaveData->SetInSupportedSave(true);
955 break;
956 case SFX_EVENT_SAVEDOCDONE:
957 case SFX_EVENT_SAVEASDOCDONE:
959 // new positions are used after "save" and "save as", but not "save to"
960 UseSheetSaveEntries(); // use positions from saved file for next saving
961 } // fall through
962 case SFX_EVENT_SAVETODOCDONE:
963 // only reset the flag, don't use the new positions
964 if (pSheetSaveData)
965 pSheetSaveData->SetInSupportedSave(false);
966 break;
967 default:
970 break;
975 // Load contents for organizer
976 bool ScDocShell::LoadFrom( SfxMedium& rMedium )
978 LoadMediumGuard aLoadGuard(&aDocument);
979 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
981 WaitObject aWait( GetActiveDialogParent() );
983 bool bRet = false;
985 if (GetMedium())
987 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
988 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
991 // until loading/saving only the styles in XML is implemented,
992 // load the whole file
993 bRet = LoadXML( &rMedium, NULL );
994 InitItems();
996 SfxObjectShell::LoadFrom( rMedium );
998 return bRet;
1001 static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert)
1003 OUStringBuffer aBuf;
1004 std::vector< OUString > aTokens;
1005 sal_Int32 n = rOption.getLength();
1006 const sal_Unicode* p = rOption.getStr();
1007 for (sal_Int32 i = 0; i < n; ++i)
1009 const sal_Unicode c = p[i];
1010 if (c == ' ')
1012 if (!aBuf.isEmpty())
1013 aTokens.push_back( aBuf.makeStringAndClear() );
1015 else
1016 aBuf.append(c);
1019 if (!aBuf.isEmpty())
1020 aTokens.push_back( aBuf.makeStringAndClear() );
1022 rLang = LanguageType( 0 );
1023 rDateConvert = false;
1025 if (aTokens.size() > 0)
1026 rLang = static_cast<LanguageType>(aTokens[0].toInt32());
1027 if (aTokens.size() > 1)
1028 rDateConvert = static_cast<bool>(aTokens[1].toInt32());
1031 bool ScDocShell::ConvertFrom( SfxMedium& rMedium )
1033 LoadMediumGuard aLoadGuard(&aDocument);
1035 bool bRet = false; // sal_False means user quit!
1036 // On error: Set error at stream
1038 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1040 GetUndoManager()->Clear();
1042 // Set optimal col width after import?
1043 bool bSetColWidths = false;
1044 bool bSetSimpleTextColWidths = false;
1045 ScColWidthParam aColWidthParam[MAXCOLCOUNT];
1046 ScRange aColWidthRange;
1047 // Set optimal row height after import?
1048 bool bSetRowHeights = false;
1050 vector<ScDocRowHeightUpdater::TabRanges> aRecalcRowRangesArray;
1052 // All filters need the complete file in one piece (not asynchronously)
1053 // So make sure that we transfer the whole file with CreateFileStream
1054 rMedium.GetPhysicalName(); //! Call CreateFileStream directly, if available
1056 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
1057 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
1059 const SfxFilter* pFilter = rMedium.GetFilter();
1060 if (pFilter)
1062 OUString aFltName = pFilter->GetFilterName();
1064 bool bCalc3 = ( aFltName.equalsAscii(pFilterSc30) );
1065 bool bCalc4 = ( aFltName.equalsAscii(pFilterSc40) );
1066 if (!bCalc3 && !bCalc4)
1067 aDocument.SetInsertingFromOtherDoc( true );
1069 if (aFltName.equalsAscii(pFilterXML))
1070 bRet = LoadXML( &rMedium, NULL );
1071 else if (aFltName.equalsAscii(pFilterSc10))
1073 SvStream* pStream = rMedium.GetInStream();
1074 if (pStream)
1076 FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
1077 if (eError != eERR_OK)
1079 if (!GetError())
1080 SetError(eError, OUString( OSL_LOG_PREFIX ));
1082 else
1083 bRet = true;
1086 else if (aFltName.equalsAscii(pFilterLotus))
1088 OUString sItStr;
1089 SfxItemSet* pSet = rMedium.GetItemSet();
1090 const SfxPoolItem* pItem;
1091 if ( pSet && SFX_ITEM_SET ==
1092 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1094 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1097 if (sItStr.isEmpty())
1099 // default for lotus import (from API without options):
1100 // IBM_437 encoding
1101 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
1104 FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
1105 ScGlobal::GetCharsetValue(sItStr));
1106 if (eError != eERR_OK)
1108 if (!GetError())
1109 SetError(eError, OUString( OSL_LOG_PREFIX ));
1111 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1112 bRet = true;
1114 else
1115 bRet = true;
1116 bSetColWidths = true;
1117 bSetRowHeights = true;
1119 else if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterExcel5) ||
1120 aFltName.equalsAscii(pFilterExcel95) || aFltName.equalsAscii(pFilterExcel97) ||
1121 aFltName.equalsAscii(pFilterEx4Temp) || aFltName.equalsAscii(pFilterEx5Temp) ||
1122 aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp) )
1124 EXCIMPFORMAT eFormat = EIF_AUTO;
1125 if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterEx4Temp) )
1126 eFormat = EIF_BIFF_LE4;
1127 else if ( aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
1128 aFltName.equalsAscii(pFilterEx5Temp) || aFltName.equalsAscii(pFilterEx95Temp) )
1129 eFormat = EIF_BIFF5;
1130 else if ( aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx97Temp) )
1131 eFormat = EIF_BIFF8;
1133 MakeDrawLayer(); //! In the filter
1134 CalcOutputFactor(); // prepare update of row height
1135 FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
1136 aDocument.UpdateFontCharSet();
1137 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
1138 aDocument.UpdateChartListenerCollection(); //! For all imports?
1140 // all graphics objects must have names
1141 aDocument.EnsureGraphicNames();
1143 if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
1145 if (!GetError())
1146 SetError(eError, OUString( OSL_LOG_PREFIX ));
1147 bRet = true;
1149 else if (eError != eERR_OK)
1151 if (!GetError())
1152 SetError(eError, OUString( OSL_LOG_PREFIX ));
1154 else
1155 bRet = true;
1157 else if (aFltName.equalsAscii(pFilterAscii))
1159 SfxItemSet* pSet = rMedium.GetItemSet();
1160 const SfxPoolItem* pItem;
1161 ScAsciiOptions aOptions;
1162 bool bOptInit = false;
1164 if ( pSet && SFX_ITEM_SET ==
1165 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1167 aOptions.ReadFromString( ((const SfxStringItem*)pItem)->GetValue() );
1168 bOptInit = true;
1171 if ( !bOptInit )
1173 // default for ascii import (from API without options):
1174 // ISO8859-1/MS_1252 encoding, comma, double quotes
1176 aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1177 aOptions.SetFieldSeps( OUString(',') );
1178 aOptions.SetTextSep( '"' );
1181 FltError eError = eERR_OK;
1182 bool bOverflowRow, bOverflowCol, bOverflowCell;
1183 bOverflowRow = bOverflowCol = bOverflowCell = false;
1185 if( ! rMedium.IsStorage() )
1187 ScImportExport aImpEx( &aDocument );
1188 aImpEx.SetExtOptions( aOptions );
1190 SvStream* pInStream = rMedium.GetInStream();
1191 if (pInStream)
1193 pInStream->SetStreamCharSet( aOptions.GetCharSet() );
1194 pInStream->Seek( 0 );
1195 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
1196 eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
1197 aDocument.StartAllListeners();
1198 sc::SetFormulaDirtyContext aCxt;
1199 aDocument.SetAllFormulasDirty(aCxt);
1200 INetURLObject aURLObjForDefaultNameSheetName(rMedium.GetName());
1201 aDocument.RenameTab(0,aURLObjForDefaultNameSheetName.GetBase());
1202 bOverflowRow = aImpEx.IsOverflowRow();
1203 bOverflowCol = aImpEx.IsOverflowCol();
1204 bOverflowCell = aImpEx.IsOverflowCell();
1206 else
1208 OSL_FAIL( "No Stream" );
1212 if (eError != eERR_OK)
1214 if (!GetError())
1215 SetError(eError, OUString( OSL_LOG_PREFIX ));
1217 else if (!GetError() && (bOverflowRow || bOverflowCol || bOverflowCell))
1219 // precedence: row, column, cell
1220 FltError nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW :
1221 (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW :
1222 SCWARN_IMPORT_CELL_OVERFLOW));
1223 SetError( nWarn, OUString( OSL_LOG_PREFIX ));
1225 bSetColWidths = true;
1226 bSetSimpleTextColWidths = true;
1228 else if (aFltName.equalsAscii(pFilterDBase))
1230 OUString sItStr;
1231 SfxItemSet* pSet = rMedium.GetItemSet();
1232 const SfxPoolItem* pItem;
1233 if ( pSet && SFX_ITEM_SET ==
1234 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1236 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1239 if (sItStr.isEmpty())
1241 // default for dBase import (from API without options):
1242 // IBM_850 encoding
1244 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
1247 ScDocRowHeightUpdater::TabRanges aRecalcRanges(0);
1248 sal_uLong eError = DBaseImport( rMedium.GetPhysicalName(),
1249 ScGlobal::GetCharsetValue(sItStr), aColWidthParam, *aRecalcRanges.mpRanges );
1250 aRecalcRowRangesArray.push_back(aRecalcRanges);
1252 if (eError != eERR_OK)
1254 if (!GetError())
1255 SetError(eError, OUString( OSL_LOG_PREFIX ));
1256 bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
1258 else
1259 bRet = true;
1261 aColWidthRange.aStart.SetRow( 1 ); // Except for the column header
1262 bSetColWidths = true;
1263 bSetSimpleTextColWidths = true;
1265 else if (aFltName.equalsAscii(pFilterDif))
1267 SvStream* pStream = rMedium.GetInStream();
1268 if (pStream)
1270 FltError eError;
1271 OUString sItStr;
1272 SfxItemSet* pSet = rMedium.GetItemSet();
1273 const SfxPoolItem* pItem;
1274 if ( pSet && SFX_ITEM_SET ==
1275 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1277 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1280 if (sItStr.isEmpty())
1282 // default for DIF import (from API without options):
1283 // ISO8859-1/MS_1252 encoding
1285 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
1288 eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
1289 ScGlobal::GetCharsetValue(sItStr));
1290 if (eError != eERR_OK)
1292 if (!GetError())
1293 SetError(eError, OUString( OSL_LOG_PREFIX ));
1295 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1296 bRet = true;
1298 else
1299 bRet = true;
1301 bSetColWidths = true;
1302 bSetSimpleTextColWidths = true;
1303 bSetRowHeights = true;
1305 else if (aFltName.equalsAscii(pFilterSylk))
1307 FltError eError = SCERR_IMPORT_UNKNOWN;
1308 if( !rMedium.IsStorage() )
1310 ScImportExport aImpEx( &aDocument );
1312 SvStream* pInStream = rMedium.GetInStream();
1313 if (pInStream)
1315 pInStream->Seek( 0 );
1316 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SOT_FORMATSTR_ID_SYLK );
1317 eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
1318 aDocument.StartAllListeners();
1319 sc::SetFormulaDirtyContext aCxt;
1320 aDocument.SetAllFormulasDirty(aCxt);
1322 else
1324 OSL_FAIL( "No Stream" );
1328 if ( eError != eERR_OK && !GetError() )
1329 SetError(eError, OUString( OSL_LOG_PREFIX ));
1330 bSetColWidths = true;
1331 bSetSimpleTextColWidths = true;
1332 bSetRowHeights = true;
1334 else if (aFltName.equalsAscii(pFilterQPro6))
1336 FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
1337 if (eError != eERR_OK)
1339 if (!GetError())
1340 SetError( eError, OUString( OSL_LOG_PREFIX ) );
1341 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1342 bRet = true;
1344 else
1345 bRet = true;
1346 // TODO: Filter should set column widths. Not doing it here, it may
1347 // result in very narrow or wide columns, depending on content.
1348 // Setting row heights makes cells with font size attribution or
1349 // wrapping enabled look nicer..
1350 bSetRowHeights = true;
1352 else if (aFltName.equalsAscii(pFilterRtf))
1354 FltError eError = SCERR_IMPORT_UNKNOWN;
1355 if( !rMedium.IsStorage() )
1357 SvStream* pInStream = rMedium.GetInStream();
1358 if (pInStream)
1360 pInStream->Seek( 0 );
1361 ScRange aRange;
1362 eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
1363 if (eError != eERR_OK)
1365 if (!GetError())
1366 SetError(eError, OUString( OSL_LOG_PREFIX ));
1368 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1369 bRet = true;
1371 else
1372 bRet = true;
1373 aDocument.StartAllListeners();
1374 sc::SetFormulaDirtyContext aCxt;
1375 aDocument.SetAllFormulasDirty(aCxt);
1376 bSetColWidths = true;
1377 bSetRowHeights = true;
1379 else
1381 OSL_FAIL( "No Stream" );
1385 if ( eError != eERR_OK && !GetError() )
1386 SetError(eError, OUString( OSL_LOG_PREFIX ));
1388 else if (aFltName.equalsAscii(pFilterHtml) || aFltName.equalsAscii(pFilterHtmlWebQ))
1390 FltError eError = SCERR_IMPORT_UNKNOWN;
1391 bool bWebQuery = aFltName.equalsAscii(pFilterHtmlWebQ);
1392 if( !rMedium.IsStorage() )
1394 SvStream* pInStream = rMedium.GetInStream();
1395 if (pInStream)
1397 LanguageType eLang = LANGUAGE_SYSTEM;
1398 bool bDateConvert = false;
1399 SfxItemSet* pSet = rMedium.GetItemSet();
1400 const SfxPoolItem* pItem;
1401 if ( pSet && SFX_ITEM_SET ==
1402 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
1404 OUString aFilterOption = (static_cast<const SfxStringItem*>(pItem))->GetValue();
1405 lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert);
1408 pInStream->Seek( 0 );
1409 ScRange aRange;
1410 // HTML does its own ColWidth/RowHeight
1411 CalcOutputFactor();
1412 SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eLang);
1413 eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
1414 GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert );
1415 if (eError != eERR_OK)
1417 if (!GetError())
1418 SetError(eError, OUString( OSL_LOG_PREFIX ));
1420 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1421 bRet = true;
1423 else
1424 bRet = true;
1425 aDocument.StartAllListeners();
1427 sc::SetFormulaDirtyContext aCxt;
1428 aDocument.SetAllFormulasDirty(aCxt);
1430 else
1432 OSL_FAIL( "No Stream" );
1436 if ( eError != eERR_OK && !GetError() )
1437 SetError(eError, OUString( OSL_LOG_PREFIX ));
1439 else
1441 if (!GetError())
1442 SetError(SCERR_IMPORT_NI, OUString( OSL_LOG_PREFIX ));
1445 if (!bCalc3)
1446 aDocument.SetInsertingFromOtherDoc( false );
1448 else
1450 OSL_FAIL("No Filter in ConvertFrom");
1453 InitItems();
1454 CalcOutputFactor();
1455 if ( bRet && (bSetColWidths || bSetRowHeights) )
1456 { // Adjust column width/row height; base 100% zoom
1457 Fraction aZoom( 1, 1 );
1458 double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom / GetOutputFactor(); // Factor is printer display ratio
1459 double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
1460 VirtualDevice aVirtDev;
1461 // all sheets (for Excel import)
1462 SCTAB nTabCount = aDocument.GetTableCount();
1463 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1465 SCCOL nEndCol;
1466 SCROW nEndRow;
1467 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1468 aColWidthRange.aEnd.SetCol( nEndCol );
1469 aColWidthRange.aEnd.SetRow( nEndRow );
1470 ScMarkData aMark;
1471 aMark.SetMarkArea( aColWidthRange );
1472 aMark.MarkToMulti();
1474 // Order is important: First width, then height
1475 if ( bSetColWidths )
1477 for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
1479 if (!bSetSimpleTextColWidths)
1480 aColWidthParam[nCol].mbSimpleText = false;
1482 sal_uInt16 nWidth = aDocument.GetOptimalColWidth(
1483 nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoom, aZoom, false, &aMark,
1484 &aColWidthParam[nCol] );
1485 aDocument.SetColWidth( nCol, nTab,
1486 nWidth + (sal_uInt16)ScGlobal::nLastColWidthExtra );
1491 if (bSetRowHeights)
1493 // Update all rows in all tables.
1494 ScSizeDeviceProvider aProv(this);
1495 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), NULL);
1496 aUpdater.update();
1498 else if (!aRecalcRowRangesArray.empty())
1500 // Update only specified row ranges for better performance.
1501 ScSizeDeviceProvider aProv(this);
1502 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &aRecalcRowRangesArray);
1503 aUpdater.update();
1506 FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
1509 // invalidate eventually temporary table areas
1510 if ( bRet )
1511 aDocument.InvalidateTableArea();
1513 bIsEmpty = false;
1515 return bRet;
1518 bool ScDocShell::LoadExternal( SfxMedium& rMed )
1520 const SfxFilter* pFilter = rMed.GetFilter();
1521 if (!pFilter)
1522 return false;
1524 if (pFilter->GetProviderName() == "orcus")
1526 ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
1527 if (!pOrcus)
1528 return false;
1530 const OUString& rFilterName = pFilter->GetName();
1531 if (rFilterName == "gnumeric")
1533 if (!pOrcus->importGnumeric(aDocument, rMed))
1534 return false;
1536 else if (rFilterName == "csv")
1538 if (!pOrcus->importCSV(aDocument, rMed))
1539 return false;
1541 else if (rFilterName == "xlsx")
1543 if (!pOrcus->importXLSX(aDocument, rMed))
1544 return false;
1546 else if (rFilterName == "ods")
1548 if (!pOrcus->importODS(aDocument, rMed))
1549 return false;
1552 FinishedLoading(SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES);
1553 return true;
1556 return false;
1560 ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
1561 : mrDocShell( rDocShell)
1563 // DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
1565 ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
1566 if (pCharts)
1567 pCharts->UpdateDirtyCharts(); // Charts to be updated.
1568 mrDocShell.aDocument.StopTemporaryChartLock();
1569 if (mrDocShell.pAutoStyleList)
1570 mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
1571 if (mrDocShell.aDocument.HasExternalRefManager())
1573 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1574 if (pRefMgr && pRefMgr->hasExternalData())
1576 pRefMgr->setAllCacheTableReferencedStati( false);
1577 mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
1580 if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD)
1581 mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
1584 ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
1586 if (mrDocShell.aDocument.HasExternalRefManager())
1588 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1589 if (pRefMgr && pRefMgr->hasExternalData())
1591 // Prevent accidental data loss due to lack of knowledge.
1592 pRefMgr->setAllCacheTableReferencedStati( true);
1598 bool ScDocShell::Save()
1600 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1602 PrepareSaveGuard aPrepareGuard( *this);
1604 SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst( this );
1605 if (pFrame1)
1607 Window* pWindow = &pFrame1->GetWindow();
1608 if ( pWindow )
1610 Window* pSysWin = pWindow->GetSystemWindow();
1611 if ( pSysWin )
1613 pSysWin->SetAccessibleName(OUString());
1617 // wait cursor is handled with progress bar
1618 bool bRet = SfxObjectShell::Save();
1619 if( bRet )
1620 bRet = SaveXML( GetMedium(), NULL );
1621 return bRet;
1624 namespace {
1627 * Remove the file name from the full path, to keep only the directory path.
1629 void popFileName(OUString& rPath)
1631 if (!rPath.isEmpty())
1633 INetURLObject aURLObj(rPath);
1634 aURLObj.removeSegment();
1635 rPath = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
1641 bool ScDocShell::SaveAs( SfxMedium& rMedium )
1643 OUString aCurPath; // empty for new document that hasn't been saved.
1644 const SfxMedium* pCurMedium = GetMedium();
1645 if (pCurMedium)
1647 aCurPath = pCurMedium->GetName();
1648 popFileName(aCurPath);
1651 if (!aCurPath.isEmpty())
1653 // current document has a path -> not a brand-new document.
1654 OUString aNewPath = rMedium.GetName();
1655 popFileName(aNewPath);
1656 OUString aRel = URIHelper::simpleNormalizedMakeRelative(aCurPath, aNewPath);
1657 if (!aRel.isEmpty())
1659 // Directory path will change before and after the save.
1660 aDocument.InvalidateStreamOnSave();
1664 ScTabViewShell* pViewShell = GetBestViewShell();
1665 bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA1);
1666 if (bNeedsRehash)
1667 // legacy xls hash double-hashed by SHA1 is also supported.
1668 bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
1670 if (pViewShell && bNeedsRehash)
1672 if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1))
1673 // password re-type cancelled. Don't save the document.
1674 return false;
1678 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1680 PrepareSaveGuard aPrepareGuard( *this);
1682 OUString aFltName = rMedium.GetFilter()->GetFilterName();
1683 bool bChartExport = aFltName.indexOf("chart8") != -1;
1685 // wait cursor is handled with progress bar
1686 bool bRet = false;
1687 if(!bChartExport)
1689 bRet = SfxObjectShell::SaveAs( rMedium );
1690 if (bRet)
1691 bRet = SaveXML( &rMedium, NULL );
1693 else
1695 bRet = SaveCurrentChart( rMedium );
1698 return bRet;
1702 bool ScDocShell::IsInformationLost()
1704 //FIXME: If we have time build a correct own way how to handle this
1705 return SfxObjectShell::IsInformationLost();
1708 namespace {
1710 // Xcl-like column width measured in characters of standard font.
1711 sal_Int32 lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth )
1713 double f = nWidth;
1714 f *= 1328.0 / 25.0;
1715 f += 90.0;
1716 f *= 1.0 / 23.0;
1717 f /= 256.0;
1719 return sal_Int32( f );
1723 void lcl_ScDocShell_GetFixedWidthString( OUString& rStr, const ScDocument& rDoc,
1724 SCTAB nTab, SCCOL nCol, bool bValue, SvxCellHorJustify eHorJust )
1726 OUString aString = rStr;
1727 sal_Int32 nLen = lcl_ScDocShell_GetColWidthInChars(
1728 rDoc.GetColWidth( nCol, nTab ) );
1729 //If the text won't fit in the column
1730 if ( nLen < aString.getLength() )
1732 OUStringBuffer aReplacement;
1733 if (bValue)
1734 aReplacement.append("###");
1735 else
1736 aReplacement.append(aString);
1737 //truncate to the number of characters that should fit, even in the
1738 //bValue case nLen might be < len ###
1739 aString = comphelper::string::truncateToLength(aReplacement, nLen).makeStringAndClear();
1741 if ( nLen > aString.getLength() )
1743 if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
1744 eHorJust = SVX_HOR_JUSTIFY_RIGHT;
1745 sal_Int32 nBlanks = nLen - aString.getLength();
1746 switch ( eHorJust )
1748 case SVX_HOR_JUSTIFY_RIGHT:
1750 OUStringBuffer aTmp;
1751 aTmp = comphelper::string::padToLength( aTmp, nBlanks, ' ' );
1752 aString = aTmp.append(aString).makeStringAndClear();
1754 break;
1755 case SVX_HOR_JUSTIFY_CENTER:
1757 sal_Int32 nLeftPad = nBlanks / 2;
1758 OUStringBuffer aTmp;
1759 comphelper::string::padToLength( aTmp, nLeftPad, ' ' );
1760 aTmp.append(aString);
1761 comphelper::string::padToLength( aTmp, nLen, ' ' );
1762 aString = aTmp.makeStringAndClear();
1764 break;
1765 default:
1767 OUStringBuffer aTmp(aString);
1768 comphelper::string::padToLength( aTmp, nLen, ' ' );
1769 aString = aTmp.makeStringAndClear();
1773 rStr = aString;
1777 void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
1778 const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
1780 OUString aString;
1781 lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, false,
1782 SVX_HOR_JUSTIFY_STANDARD );
1783 rStream.WriteUnicodeOrByteText( aString );
1786 template<typename StrT, typename SepCharT>
1787 sal_Int32 getTextSepPos(
1788 const StrT& rStr, const ScImportOptions& rAsciiOpt, const SepCharT& rTextSep, const SepCharT& rFieldSep, bool& rNeedQuotes)
1790 // #i116636# quotes are needed if text delimiter (quote), field delimiter,
1791 // or LF is in the cell text.
1792 sal_Int32 nPos = rStr.indexOf(rTextSep);
1793 rNeedQuotes = rAsciiOpt.bQuoteAllText || (nPos >= 0) ||
1794 (rStr.indexOf(rFieldSep) >= 0) ||
1795 (rStr.indexOf('\n') >= 0);
1796 return nPos;
1799 template<typename StrT, typename StrBufT>
1800 void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr)
1802 while (nPos >= 0)
1804 StrBufT aBuf(rStr);
1805 aBuf.insert(nPos, rStrDelim);
1806 rStr = aBuf.makeStringAndClear();
1807 nPos = rStr.indexOf(rStrDelim, nPos+1+rStrDelim.getLength());
1813 void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
1815 sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
1816 sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
1817 rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet;
1818 bool bFixedWidth = rAsciiOpt.bFixedWidth;
1819 bool bSaveAsShown = rAsciiOpt.bSaveAsShown;
1820 bool bShowFormulas = rAsciiOpt.bSaveFormulas;
1822 rtl_TextEncoding eOldCharSet = rStream.GetStreamCharSet();
1823 rStream.SetStreamCharSet( eCharSet );
1824 sal_uInt16 nOldNumberFormatInt = rStream.GetNumberFormatInt();
1825 OString aStrDelimEncoded; // only used if not Unicode
1826 OUString aStrDelimDecoded; // only used if context encoding
1827 OString aDelimEncoded;
1828 OUString aDelimDecoded;
1829 bool bContextOrNotAsciiEncoding;
1830 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
1832 rStream.StartWritingUnicodeText();
1833 bContextOrNotAsciiEncoding = false;
1835 else
1837 aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
1838 aDelimEncoded = OString(&cDelim, 1, eCharSet);
1839 rtl_TextEncodingInfo aInfo;
1840 aInfo.StructSize = sizeof(aInfo);
1841 if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
1843 bContextOrNotAsciiEncoding =
1844 (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
1845 ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
1846 if ( bContextOrNotAsciiEncoding )
1848 aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet);
1849 aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet);
1852 else
1853 bContextOrNotAsciiEncoding = false;
1856 SCCOL nStartCol = 0;
1857 SCROW nStartRow = 0;
1858 SCTAB nTab = GetSaveTab();
1859 SCCOL nEndCol;
1860 SCROW nEndRow;
1861 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1863 ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
1865 OUString aString;
1867 bool bTabProtect = aDocument.IsTabProtected( nTab );
1869 SCCOL nCol;
1870 SCROW nRow;
1871 SCCOL nNextCol = nStartCol;
1872 SCROW nNextRow = nStartRow;
1873 SCCOL nEmptyCol;
1874 SCROW nEmptyRow;
1875 SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
1877 ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
1878 nEndCol, nEndRow );
1879 ScRefCellValue* pCell;
1880 while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
1882 bool bProgress = false; // only upon line change
1883 if ( nNextRow < nRow )
1884 { // empty rows or/and empty columns up to end of row
1885 bProgress = true;
1886 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
1887 { // remaining columns of last row
1888 if ( bFixedWidth )
1889 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1890 aDocument, nTab, nEmptyCol );
1891 else if ( cDelim != 0 )
1892 rStream.WriteUniOrByteChar( cDelim );
1894 endlub( rStream );
1895 nNextRow++;
1896 for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
1897 { // completely empty rows
1898 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
1900 if ( bFixedWidth )
1901 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1902 aDocument, nTab, nEmptyCol );
1903 else if ( cDelim != 0 )
1904 rStream.WriteUniOrByteChar( cDelim );
1906 endlub( rStream );
1908 for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
1909 { // empty columns at beginning of row
1910 if ( bFixedWidth )
1911 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1912 aDocument, nTab, nEmptyCol );
1913 else if ( cDelim != 0 )
1914 rStream.WriteUniOrByteChar( cDelim );
1916 nNextRow = nRow;
1918 else if ( nNextCol < nCol )
1919 { // empty columns in same row
1920 for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
1921 { // columns in between
1922 if ( bFixedWidth )
1923 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1924 aDocument, nTab, nEmptyCol );
1925 else if ( cDelim != 0 )
1926 rStream.WriteUniOrByteChar( cDelim );
1929 if ( nCol == nEndCol )
1931 bProgress = true;
1932 nNextCol = nStartCol;
1933 nNextRow = nRow + 1;
1935 else
1936 nNextCol = nCol + 1;
1938 CellType eType = pCell->meType;
1939 ScAddress aPos(nCol, nRow, nTab);
1940 if ( bTabProtect )
1942 const ScProtectionAttr* pProtAttr =
1943 (const ScProtectionAttr*) aDocument.GetAttr(
1944 nCol, nRow, nTab, ATTR_PROTECTION );
1945 if ( pProtAttr->GetHideCell() ||
1946 ( eType == CELLTYPE_FORMULA && bShowFormulas &&
1947 pProtAttr->GetHideFormula() ) )
1948 eType = CELLTYPE_NONE; // hide
1950 bool bString;
1951 switch ( eType )
1953 case CELLTYPE_NONE:
1954 aString = "";
1955 bString = false;
1956 break;
1957 case CELLTYPE_FORMULA :
1959 sal_uInt16 nErrCode;
1960 if ( bShowFormulas )
1962 pCell->mpFormula->GetFormula(aString);
1963 bString = true;
1965 else if ((nErrCode = pCell->mpFormula->GetErrCode()) != 0)
1967 aString = ScGlobal::GetErrorString( nErrCode );
1968 bString = true;
1970 else if (pCell->mpFormula->IsValue())
1972 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1973 if ( bFixedWidth || bSaveAsShown )
1975 Color* pDummy;
1976 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1977 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
1979 else
1981 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
1982 bString = false;
1985 else
1987 if ( bSaveAsShown )
1989 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1990 Color* pDummy;
1991 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1993 else
1994 aString = pCell->mpFormula->GetString().getString();
1995 bString = true;
1998 break;
1999 case CELLTYPE_STRING :
2000 if ( bSaveAsShown )
2002 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
2003 Color* pDummy;
2004 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2006 else
2007 aString = pCell->mpString->getString();
2008 bString = true;
2009 break;
2010 case CELLTYPE_EDIT :
2012 const EditTextObject* pObj = pCell->mpEditText;
2013 EditEngine& rEngine = aDocument.GetEditEngine();
2014 rEngine.SetText( *pObj);
2015 aString = rEngine.GetText(); // including LF
2016 bString = true;
2018 break;
2019 case CELLTYPE_VALUE :
2021 sal_uInt32 nFormat;
2022 aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
2023 if ( bFixedWidth || bSaveAsShown )
2025 Color* pDummy;
2026 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2027 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
2029 else
2031 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
2032 bString = false;
2035 break;
2036 default:
2037 OSL_FAIL( "ScDocShell::AsciiSave: unknown CellType" );
2038 aString = "";
2039 bString = false;
2042 if ( bFixedWidth )
2044 SvxCellHorJustify eHorJust = (SvxCellHorJustify)
2045 ((const SvxHorJustifyItem*) aDocument.GetAttr( nCol, nRow,
2046 nTab, ATTR_HOR_JUSTIFY ))->GetValue();
2047 lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
2048 !bString, eHorJust );
2049 rStream.WriteUnicodeOrByteText( aString );
2051 else
2053 OUString aUniString = aString;// TODO: remove that later
2054 if (!bString && cStrDelim != 0 && !aUniString.isEmpty())
2056 sal_Unicode c = aUniString[0];
2057 bString = (c == cStrDelim || c == ' ' ||
2058 aUniString.endsWith(" ") ||
2059 aUniString.indexOf(cStrDelim) >= 0);
2060 if (!bString && cDelim != 0)
2061 bString = (aUniString.indexOf(cDelim) >= 0);
2063 if ( bString )
2065 if ( cStrDelim != 0 ) //@ BugId 55355
2067 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
2069 bool bNeedQuotes = false;
2070 sal_Int32 nPos = getTextSepPos(
2071 aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes);
2073 escapeTextSep<OUString, OUStringBuffer>(
2074 nPos, OUString(cStrDelim), aUniString);
2076 if ( bNeedQuotes )
2077 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2078 write_uInt16s_FromOUString(rStream, aUniString);
2079 if ( bNeedQuotes )
2080 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2082 else
2084 // This is nasty. The Unicode to byte encoding
2085 // may convert typographical quotation marks to ASCII
2086 // quotation marks, which may interfer with the delimiter,
2087 // so we have to escape delimiters after the string has
2088 // been encoded. Since this may happen also with UTF-8
2089 // encoded typographical quotation marks if such was
2090 // specified as a delimiter we have to check for the full
2091 // encoded delimiter string, not just one character.
2092 // Now for RTL_TEXTENCODING_ISO_2022_... and similar brain
2093 // dead encodings where one code point (and especially a
2094 // low ASCII value) may represent different characters, we
2095 // have to convert forth and back and forth again. Same for
2096 // UTF-7 since it is a context sensitive encoding too.
2098 if ( bContextOrNotAsciiEncoding )
2100 // to byte encoding
2101 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2102 // back to Unicode
2103 OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
2105 // search on re-decoded string
2106 bool bNeedQuotes = false;
2107 sal_Int32 nPos = getTextSepPos(
2108 aStrDec, rAsciiOpt, aStrDelimDecoded, aDelimDecoded, bNeedQuotes);
2110 escapeTextSep<OUString, OUStringBuffer>(
2111 nPos, aStrDelimDecoded, aStrDec);
2113 // write byte re-encoded
2114 if ( bNeedQuotes )
2115 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2116 rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
2117 if ( bNeedQuotes )
2118 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2120 else
2122 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2124 // search on encoded string
2125 bool bNeedQuotes = false;
2126 sal_Int32 nPos = getTextSepPos(
2127 aStrEnc, rAsciiOpt, aStrDelimEncoded, aDelimEncoded, bNeedQuotes);
2129 escapeTextSep<OString, OStringBuffer>(
2130 nPos, aStrDelimEncoded, aStrEnc);
2132 // write byte encoded
2133 if ( bNeedQuotes )
2134 rStream.Write(
2135 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2136 rStream.Write(aStrEnc.getStr(), aStrEnc.getLength());
2137 if ( bNeedQuotes )
2138 rStream.Write(
2139 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2143 else
2144 rStream.WriteUnicodeOrByteText( aUniString );
2146 else
2147 rStream.WriteUnicodeOrByteText( aUniString );
2150 if( nCol < nEndCol )
2152 if(cDelim!=0) //@ BugId 55355
2153 rStream.WriteUniOrByteChar( cDelim );
2155 else
2156 endlub( rStream );
2158 if ( bProgress )
2159 aProgress.SetStateOnPercent( nRow );
2162 // write out empty if requested
2163 if ( nNextRow <= nEndRow )
2165 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
2166 { // remaining empty columns of last row
2167 if ( bFixedWidth )
2168 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2169 aDocument, nTab, nEmptyCol );
2170 else if ( cDelim != 0 )
2171 rStream.WriteUniOrByteChar( cDelim );
2173 endlub( rStream );
2174 nNextRow++;
2176 for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
2177 { // entire empty rows
2178 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
2180 if ( bFixedWidth )
2181 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2182 aDocument, nTab, nEmptyCol );
2183 else if ( cDelim != 0 )
2184 rStream.WriteUniOrByteChar( cDelim );
2186 endlub( rStream );
2189 rStream.SetStreamCharSet( eOldCharSet );
2190 rStream.SetNumberFormatInt( nOldNumberFormatInt );
2193 bool ScDocShell::ConvertTo( SfxMedium &rMed )
2195 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
2197 // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
2198 // it's already in ExecuteSave (as for Save and SaveAs)
2200 if (pAutoStyleList)
2201 pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now
2202 if (GetCreateMode()== SFX_CREATE_MODE_STANDARD)
2203 SfxObjectShell::SetVisArea( Rectangle() ); // Edited normally -> no VisArea
2205 OSL_ENSURE( rMed.GetFilter(), "Filter == 0" );
2207 bool bRet = false;
2208 OUString aFltName = rMed.GetFilter()->GetFilterName();
2210 if (aFltName.equalsAscii(pFilterXML))
2212 //TODO/LATER: this shouldn't happen!
2213 OSL_FAIL("XML filter in ConvertFrom?!");
2214 bRet = SaveXML( &rMed, NULL );
2216 else if (aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
2217 aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx5Temp) ||
2218 aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp))
2220 WaitObject aWait( GetActiveDialogParent() );
2222 bool bDoSave = true;
2223 if( ScTabViewShell* pViewShell = GetBestViewShell() )
2225 ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
2226 if( !pExtDocOpt )
2227 aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
2228 pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
2230 /* #i104990# If the imported document contains a medium
2231 password, determine if we can save it, otherwise ask the users
2232 whether they want to save without it. */
2233 if( (rMed.GetFilter()->GetFilterFlags() & SFX_FILTER_ENCRYPTION) == 0 )
2235 SfxItemSet* pItemSet = rMed.GetItemSet();
2236 const SfxPoolItem* pItem = 0;
2237 if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, true, &pItem ) == SFX_ITEM_SET )
2239 bDoSave = ScWarnPassword::WarningOnPassword( rMed );
2240 // #i42858# remove password from medium (warn only one time)
2241 if( bDoSave )
2242 pItemSet->ClearItem( SID_PASSWORD );
2246 if( bDoSave )
2248 bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
2249 bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
2253 if( bDoSave )
2255 ExportFormatExcel eFormat = ExpBiff5;
2256 if( aFltName.equalsAscii( pFilterExcel97 ) || aFltName.equalsAscii( pFilterEx97Temp ) )
2257 eFormat = ExpBiff8;
2258 FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
2260 if( eError && !GetError() )
2261 SetError( eError, OUString( OSL_LOG_PREFIX ) );
2263 // don't return false for warnings
2264 bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
2266 else
2268 // export aborted, i.e. "Save without password" warning
2269 SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
2272 else if (aFltName.equalsAscii(pFilterAscii))
2274 SvStream* pStream = rMed.GetOutStream();
2275 if (pStream)
2277 OUString sItStr;
2278 SfxItemSet* pSet = rMed.GetItemSet();
2279 const SfxPoolItem* pItem;
2280 if ( pSet && SFX_ITEM_SET ==
2281 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2283 sItStr = ((const SfxStringItem*)pItem)->GetValue();
2286 if ( sItStr.isEmpty() )
2288 // default for ascii export (from API without options):
2289 // ISO8859-1/MS_1252 encoding, comma, double quotes
2291 ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
2292 sItStr = aDefOptions.BuildString();
2295 WaitObject aWait( GetActiveDialogParent() );
2296 ScImportOptions aOptions( sItStr );
2297 AsciiSave( *pStream, aOptions );
2298 bRet = true;
2300 if (aDocument.GetTableCount() > 1)
2301 if (!rMed.GetError())
2302 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2305 else if (aFltName.equalsAscii(pFilterDBase))
2307 OUString sCharSet;
2308 SfxItemSet* pSet = rMed.GetItemSet();
2309 const SfxPoolItem* pItem;
2310 if ( pSet && SFX_ITEM_SET ==
2311 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2313 sCharSet = ((const SfxStringItem*)pItem)->GetValue();
2316 if (sCharSet.isEmpty())
2318 // default for dBase export (from API without options):
2319 // IBM_850 encoding
2321 sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
2324 WaitObject aWait( GetActiveDialogParent() );
2325 // FIXME: Hack so that the Sba opened TempFile can be overwritten
2326 rMed.CloseOutStream();
2327 bool bHasMemo = false;
2329 sal_uLong eError = DBaseExport(
2330 rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo);
2332 if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
2334 eError = eERR_OK;
2337 INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE );
2338 if ( bHasMemo )
2339 aTmpFile.setExtension(OUString("dbt"));
2340 if ( eError != eERR_OK )
2342 if (!GetError())
2343 SetError(eError, OUString( OSL_LOG_PREFIX ));
2344 if ( bHasMemo && IsDocument( aTmpFile ) )
2345 KillFile( aTmpFile );
2347 else
2349 bRet = true;
2350 if ( bHasMemo )
2352 SfxStringItem* pNameItem =
2353 (SfxStringItem*) rMed.GetItemSet()->GetItem( SID_FILE_NAME );
2354 INetURLObject aDbtFile( pNameItem->GetValue(), INET_PROT_FILE );
2355 aDbtFile.setExtension(OUString("dbt"));
2356 if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
2357 bRet = false;
2358 if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
2359 bRet = false;
2360 if ( !bRet )
2362 KillFile( aTmpFile );
2363 if ( !GetError() )
2364 SetError( SCERR_EXPORT_DATA, OUString( OSL_LOG_PREFIX ) );
2369 else if (aFltName.equalsAscii(pFilterDif))
2371 SvStream* pStream = rMed.GetOutStream();
2372 if (pStream)
2374 OUString sItStr;
2375 SfxItemSet* pSet = rMed.GetItemSet();
2376 const SfxPoolItem* pItem;
2377 if ( pSet && SFX_ITEM_SET ==
2378 pSet->GetItemState( SID_FILE_FILTEROPTIONS, true, &pItem ) )
2380 sItStr = ((const SfxStringItem*)pItem)->GetValue();
2383 if (sItStr.isEmpty())
2385 // default for DIF export (from API without options):
2386 // ISO8859-1/MS_1252 encoding
2388 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
2391 WaitObject aWait( GetActiveDialogParent() );
2392 ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
2393 ScGlobal::GetCharsetValue(sItStr) );
2394 bRet = true;
2396 if (aDocument.GetTableCount() > 1)
2397 if (!rMed.GetError())
2398 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2401 else if (aFltName.equalsAscii(pFilterSylk))
2403 SvStream* pStream = rMed.GetOutStream();
2404 if ( pStream )
2406 WaitObject aWait( GetActiveDialogParent() );
2408 SCCOL nEndCol;
2409 SCROW nEndRow;
2410 aDocument.GetCellArea( 0, nEndCol, nEndRow );
2411 ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
2413 ScImportExport aImExport( &aDocument, aRange );
2414 aImExport.SetFormulas( true );
2415 bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_SYLK );
2418 else if (aFltName.equalsAscii(pFilterHtml))
2420 SvStream* pStream = rMed.GetOutStream();
2421 if ( pStream )
2423 SfxItemSet* pSet = rMed.GetItemSet();
2424 const SfxPoolItem* pItem;
2425 OUString sFilterOptions;
2427 if (pSet->GetItemState(SID_FILE_FILTEROPTIONS, true, &pItem) == SFX_ITEM_SET)
2428 sFilterOptions = ((SfxStringItem*)pItem)->GetValue();
2430 WaitObject aWait(GetActiveDialogParent());
2431 ScImportExport aImExport(&aDocument);
2432 aImExport.SetStreamPath(rMed.GetName());
2433 aImExport.SetFilterOptions(sFilterOptions);
2434 bRet = aImExport.ExportStream(*pStream, rMed.GetBaseURL(true), SOT_FORMATSTR_ID_HTML);
2435 if (bRet && !aImExport.GetNonConvertibleChars().isEmpty())
2437 SetError(*new StringErrorInfo(
2438 SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
2439 aImExport.GetNonConvertibleChars(),
2440 ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO), OUString(OSL_LOG_PREFIX));
2444 else
2446 if (GetError())
2447 SetError(SCERR_IMPORT_NI, OUString(OSL_LOG_PREFIX));
2449 return bRet;
2452 bool ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
2454 return SfxObjectShell::SaveCompleted( xStor );
2458 bool ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
2460 bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
2462 // SC_HINT_DOC_SAVED for change ReadOnly -> Read/Write
2463 Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
2464 return bRet;
2468 bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId )
2470 // #i112634# ask VBA event handlers whether to save or print the document
2472 using namespace ::com::sun::star::script::vba;
2474 sal_Int32 nVbaEventId = VBAEventId::NO_EVENT;
2475 uno::Sequence< uno::Any > aArgs;
2476 switch( nSlotId )
2478 case SID_SAVEDOC:
2479 case SID_SAVEASDOC:
2480 nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE;
2481 aArgs.realloc( 1 );
2482 aArgs[ 0 ] <<= (nSlotId == SID_SAVEASDOC);
2483 break;
2484 case SID_PRINTDOC:
2485 case SID_PRINTDOCDIRECT:
2486 nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT;
2487 break;
2490 bool bSlotExecutable = true;
2491 if( nVbaEventId != VBAEventId::NO_EVENT ) try
2493 uno::Reference< XVBAEventProcessor > xEventProcessor( aDocument.GetVbaEventProcessor(), uno::UNO_QUERY_THROW );
2494 xEventProcessor->processVbaEvent( nVbaEventId, aArgs );
2496 catch( util::VetoException& )
2498 bSlotExecutable = false;
2500 catch( uno::Exception& )
2503 return bSlotExecutable;
2507 bool ScDocShell::PrepareClose( bool bUI )
2509 if(SC_MOD()->GetCurRefDlgId()>0)
2511 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
2512 if( pFrame )
2514 SfxViewShell* p = pFrame->GetViewShell();
2515 ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
2516 if(pViewSh!=NULL)
2518 Window *pWin=pViewSh->GetWindow();
2519 if(pWin!=NULL) pWin->GrabFocus();
2523 return false;
2525 if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
2527 ErrorMessage(STR_CLOSE_ERROR_LINK);
2528 return false;
2531 DoEnterHandler();
2533 // start 'Workbook_BeforeClose' VBA event handler for possible veto
2534 if( !IsInPrepareClose() )
2538 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( aDocument.GetVbaEventProcessor(), uno::UNO_SET_THROW );
2539 uno::Sequence< uno::Any > aArgs;
2540 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs );
2542 catch( util::VetoException& )
2544 // if event processor throws VetoException, macro has vetoed close
2545 return false;
2547 catch( uno::Exception& )
2551 // end handler code
2553 bool nRet = SfxObjectShell::PrepareClose( bUI );
2554 if (nRet) // true == close
2555 aDocument.EnableIdle(false); // Do not mess around with it anymore!
2557 return nRet;
2560 void ScDocShell::PrepareReload()
2562 SfxObjectShell::PrepareReload(); // FIXME: Doesn't do a thing?
2564 // The Disconnect of DDE Links can trigger a Reschedule.
2565 // If the DDE Links are not deleted before the Document dtor,
2566 // the DDE Link Update for this Document can be triggered ofrom this Reschedule on Reload.
2567 // This causes a hang.
2569 // Thus: Disconnect the DDE Links of the old Document before Reload
2570 aDocument.GetDocLinkManager().disconnectDdeLinks();
2574 OUString ScDocShell::GetOwnFilterName()
2576 return OUString(pFilterSc50);
2579 OUString ScDocShell::GetHtmlFilterName()
2581 return OUString(pFilterHtml);
2584 OUString ScDocShell::GetWebQueryFilterName()
2586 return OUString(pFilterHtmlWebQ);
2589 OUString ScDocShell::GetAsciiFilterName()
2591 return OUString(pFilterAscii);
2594 OUString ScDocShell::GetLotusFilterName()
2596 return OUString(pFilterLotus);
2599 OUString ScDocShell::GetDBaseFilterName()
2601 return OUString(pFilterDBase);
2604 OUString ScDocShell::GetDifFilterName()
2606 return OUString(pFilterDif);
2609 bool ScDocShell::HasAutomaticTableName( const OUString& rFilter )
2611 // sal_True for those filters that keep the default table name
2612 // (which is language specific)
2614 return rFilter.equalsAscii( pFilterAscii )
2615 || rFilter.equalsAscii( pFilterLotus )
2616 || rFilter.equalsAscii( pFilterExcel4 )
2617 || rFilter.equalsAscii( pFilterEx4Temp )
2618 || rFilter.equalsAscii( pFilterDBase )
2619 || rFilter.equalsAscii( pFilterDif )
2620 || rFilter.equalsAscii( pFilterSylk )
2621 || rFilter.equalsAscii( pFilterHtml )
2622 || rFilter.equalsAscii( pFilterRtf );
2625 #if ! ENABLE_TELEPATHY
2626 ScDocFunc *ScDocShell::CreateDocFunc()
2628 return new ScDocFuncDirect( *this );
2630 #else
2631 ScCollaboration* ScDocShell::GetCollaboration()
2633 return mpCollaboration;
2635 #endif
2637 ScDocShell::ScDocShell( const ScDocShell& rShell ) :
2638 SvRefBase(),
2639 SotObject(),
2640 SfxObjectShell( rShell.GetCreateMode() ),
2641 SfxListener(),
2642 aDocument ( SCDOCMODE_DOCUMENT, this ),
2643 aDdeTextFmt(OUString("TEXT")),
2644 nPrtToScreenFactor( 1.0 ),
2645 pImpl ( new DocShell_Impl ),
2646 bHeaderOn ( true ),
2647 bFooterOn ( true ),
2648 bIsEmpty ( true ),
2649 bIsInUndo ( false ),
2650 bDocumentModifiedPending( false ),
2651 bUpdateEnabled ( true ),
2652 nDocumentLock ( 0 ),
2653 nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2654 pOldAutoDBRange ( NULL ),
2655 pDocHelper ( NULL ),
2656 pAutoStyleList ( NULL ),
2657 pPaintLockData ( NULL ),
2658 pSolverSaveData ( NULL ),
2659 pSheetSaveData ( NULL ),
2660 pModificator ( NULL )
2661 #if ENABLE_TELEPATHY
2662 , mpCollaboration( new ScCollaboration( this ) )
2663 #endif
2665 SetPool( &SC_MOD()->GetPool() );
2667 bIsInplace = rShell.bIsInplace;
2669 pDocFunc = CreateDocFunc();
2671 // SetBaseModel needs exception handling
2672 ScModelObj::CreateAndSet( this );
2674 StartListening(*this);
2675 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2676 if (pStlPool)
2677 StartListening(*pStlPool);
2679 GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
2680 SetHelpId( HID_SCSHELL_DOCSH );
2682 // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2685 ScDocShell::ScDocShell( const sal_uInt64 i_nSfxCreationFlags ) :
2686 SfxObjectShell( i_nSfxCreationFlags ),
2687 aDocument ( SCDOCMODE_DOCUMENT, this ),
2688 aDdeTextFmt(OUString("TEXT")),
2689 nPrtToScreenFactor( 1.0 ),
2690 pImpl ( new DocShell_Impl ),
2691 bHeaderOn ( true ),
2692 bFooterOn ( true ),
2693 bIsEmpty ( true ),
2694 bIsInUndo ( false ),
2695 bDocumentModifiedPending( false ),
2696 bUpdateEnabled ( true ),
2697 nDocumentLock ( 0 ),
2698 nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2699 pOldAutoDBRange ( NULL ),
2700 pDocHelper ( NULL ),
2701 pAutoStyleList ( NULL ),
2702 pPaintLockData ( NULL ),
2703 pSolverSaveData ( NULL ),
2704 pSheetSaveData ( NULL ),
2705 pModificator ( NULL )
2706 #if ENABLE_TELEPATHY
2707 , mpCollaboration( new ScCollaboration( this ) )
2708 #endif
2710 SetPool( &SC_MOD()->GetPool() );
2712 bIsInplace = (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
2713 // Will be reset if not in place
2715 pDocFunc = CreateDocFunc();
2717 // SetBaseModel needs exception handling
2718 ScModelObj::CreateAndSet( this );
2720 StartListening(*this);
2721 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2722 if (pStlPool)
2723 StartListening(*pStlPool);
2724 SetHelpId( HID_SCSHELL_DOCSH );
2726 aDocument.GetDBCollection()->SetRefreshHandler(
2727 LINK( this, ScDocShell, RefreshDBDataHdl ) );
2729 // InitItems and CalcOutputFactor are called now in Load/ConvertFrom/InitNew
2732 ScDocShell::~ScDocShell()
2734 ResetDrawObjectShell(); // If the Drawing Layer still tries to access it, access it
2736 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2737 if (pStlPool)
2738 EndListening(*pStlPool);
2739 EndListening(*this);
2741 delete pAutoStyleList;
2743 SfxApplication *pSfxApp = SFX_APP();
2744 if ( pSfxApp->GetDdeService() ) // Delete DDE for Document
2745 pSfxApp->RemoveDdeTopic( this );
2747 delete pDocFunc;
2748 delete aDocument.mpUndoManager;
2749 aDocument.mpUndoManager = 0;
2750 delete pImpl;
2752 delete pPaintLockData;
2754 delete pSolverSaveData;
2755 delete pSheetSaveData;
2756 delete pOldAutoDBRange;
2758 if (pModificator)
2760 OSL_FAIL("The Modificator should not exist");
2761 delete pModificator;
2763 #if ENABLE_TELEPATHY
2764 delete mpCollaboration;
2765 #endif
2768 ::svl::IUndoManager* ScDocShell::GetUndoManager()
2770 return aDocument.GetUndoManager();
2773 void ScDocShell::SetModified( bool bModified )
2775 if ( SfxObjectShell::IsEnableSetModified() )
2777 SfxObjectShell::SetModified( bModified );
2778 Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
2783 void ScDocShell::SetDocumentModified( bool bIsModified /* = true */ )
2785 // BroadcastUno must also happen right away with pPaintLockData
2786 // FIXME: Also for SetDrawModified, if Drawing is connected
2787 // FIXME: Then own Hint?
2789 if ( pPaintLockData && bIsModified )
2791 // #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results
2792 // of RecalcModeAlways formulas (like OFFSET) after modifying cells
2793 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2794 aDocument.InvalidateTableArea(); // #i105279# needed here
2795 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2797 pPaintLockData->SetModified(); // Later on ...
2798 return;
2801 SetDrawModified( bIsModified );
2803 if ( bIsModified )
2805 if ( aDocument.IsAutoCalcShellDisabled() )
2806 SetDocumentModifiedPending( true );
2807 else
2809 SetDocumentModifiedPending( false );
2810 aDocument.InvalidateStyleSheetUsage();
2811 aDocument.InvalidateTableArea();
2812 aDocument.InvalidateLastTableOpParams();
2813 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2814 if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
2815 aDocument.CalcFormulaTree( true );
2816 PostDataChanged();
2818 // Detective AutoUpdate:
2819 // Update if formulas were modified (DetectiveDirty) or the list contains
2820 // "Trace Error" entries (Trace Error can look completely different
2821 // after changes to non-formula cells).
2823 ScDetOpList* pList = aDocument.GetDetOpList();
2824 if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
2825 pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
2827 GetDocFunc().DetectiveRefresh(true); // sal_True = caused by automatic update
2829 aDocument.SetDetectiveDirty(false); // always reset, also if not refreshed
2832 // notify UNO objects after BCA_BRDCST_ALWAYS etc.
2833 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2838 * SetDrawModified - without Formula update
2840 * Drawing also needs to be updated for the normal SetDocumentModified
2841 * e.g.: when deleting tables etc.
2843 void ScDocShell::SetDrawModified( bool bIsModified /* = true */ )
2845 bool bUpdate = bIsModified != IsModified();
2847 SetModified( bIsModified );
2849 SfxBindings* pBindings = GetViewBindings();
2850 if (bUpdate)
2852 if (pBindings)
2854 pBindings->Invalidate( SID_SAVEDOC );
2855 pBindings->Invalidate( SID_DOC_MODIFIED );
2859 if (bIsModified)
2861 if (pBindings)
2863 // #i105960# Undo etc used to be volatile.
2864 // They always have to be invalidated, including drawing layer or row height changes
2865 // (but not while pPaintLockData is set).
2866 pBindings->Invalidate( SID_UNDO );
2867 pBindings->Invalidate( SID_REDO );
2868 pBindings->Invalidate( SID_REPEAT );
2871 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
2873 aDocument.UpdateChartListenerCollection();
2874 SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
2876 SC_MOD()->AnythingChanged();
2880 void ScDocShell::SetInUndo(bool bSet)
2882 bIsInUndo = bSet;
2886 void ScDocShell::GetDocStat( ScDocStat& rDocStat )
2888 SfxPrinter* pPrinter = GetPrinter();
2890 aDocument.GetDocStat( rDocStat );
2891 rDocStat.nPageCount = 0;
2893 if ( pPrinter )
2894 for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
2895 rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount +
2896 (sal_uInt16) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
2900 SfxDocumentInfoDialog* ScDocShell::CreateDocumentInfoDialog(
2901 Window *pParent, const SfxItemSet &rSet )
2903 SfxDocumentInfoDialog* pDlg = new SfxDocumentInfoDialog( pParent, rSet );
2904 ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
2906 // Only for statistics, if this Doc is shown; not from the Doc Manager
2907 if( pDocSh == this )
2909 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
2910 OSL_ENSURE(pFact, "ScAbstractFactory create fail!");
2911 ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
2912 OSL_ENSURE(ScDocStatPageCreate, "Tabpage create fail!");
2913 pDlg->AddFontTabPage();
2914 pDlg->AddTabPage( 42,
2915 ScGlobal::GetRscString( STR_DOC_STAT ),
2916 ScDocStatPageCreate,
2917 NULL);
2919 return pDlg;
2922 Window* ScDocShell::GetActiveDialogParent()
2924 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2925 if ( pViewSh )
2926 return pViewSh->GetDialogParent();
2927 else
2928 return Application::GetDefDialogParent();
2931 void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
2933 delete pSolverSaveData;
2934 pSolverSaveData = new ScOptSolverSave( rData );
2937 ScSheetSaveData* ScDocShell::GetSheetSaveData()
2939 if (!pSheetSaveData)
2940 pSheetSaveData = new ScSheetSaveData;
2942 return pSheetSaveData;
2945 namespace {
2947 void removeKeysIfExists(Reference<ui::XAcceleratorConfiguration>& xScAccel, const vector<const awt::KeyEvent*>& rKeys)
2949 vector<const awt::KeyEvent*>::const_iterator itr = rKeys.begin(), itrEnd = rKeys.end();
2950 for (; itr != itrEnd; ++itr)
2952 const awt::KeyEvent* p = *itr;
2953 if (!p)
2954 continue;
2958 xScAccel->removeKeyEvent(*p);
2960 catch (const container::NoSuchElementException&) {}
2966 void ScDocShell::ResetKeyBindings( ScOptionsUtil::KeyBindingType eType )
2968 using namespace ::com::sun::star::ui;
2970 Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2971 if (!xContext.is())
2972 return;
2974 Reference<XModuleUIConfigurationManagerSupplier> xModuleCfgSupplier(
2975 theModuleUIConfigurationManagerSupplier::get(xContext) );
2977 // Grab the Calc configuration.
2978 Reference<XUIConfigurationManager> xConfigMgr =
2979 xModuleCfgSupplier->getUIConfigurationManager(
2980 OUString("com.sun.star.sheet.SpreadsheetDocument"));
2982 if (!xConfigMgr.is())
2983 return;
2985 // shortcut manager
2986 Reference<XAcceleratorConfiguration> xScAccel = xConfigMgr->getShortCutManager();
2988 if (!xScAccel.is())
2989 return;
2991 vector<const awt::KeyEvent*> aKeys;
2992 aKeys.reserve(4);
2994 // Backsapce key
2995 awt::KeyEvent aBackspace;
2996 aBackspace.KeyCode = awt::Key::BACKSPACE;
2997 aBackspace.Modifiers = 0;
2998 aKeys.push_back(&aBackspace);
3000 // Delete key
3001 awt::KeyEvent aDelete;
3002 aDelete.KeyCode = awt::Key::DELETE;
3003 aDelete.Modifiers = 0;
3004 aKeys.push_back(&aDelete);
3006 // Ctrl-D
3007 awt::KeyEvent aCtrlD;
3008 aCtrlD.KeyCode = awt::Key::D;
3009 aCtrlD.Modifiers = awt::KeyModifier::MOD1;
3010 aKeys.push_back(&aCtrlD);
3012 // Alt-Down
3013 awt::KeyEvent aAltDown;
3014 aAltDown.KeyCode = awt::Key::DOWN;
3015 aAltDown.Modifiers = awt::KeyModifier::MOD2;
3016 aKeys.push_back(&aAltDown);
3018 // Remove all involved keys first, because swapping commands don't work
3019 // well without doing this.
3020 removeKeysIfExists(xScAccel, aKeys);
3021 xScAccel->store();
3023 switch (eType)
3025 case ScOptionsUtil::KEY_DEFAULT:
3026 xScAccel->setKeyEvent(aDelete, OUString(".uno:ClearContents"));
3027 xScAccel->setKeyEvent(aBackspace, OUString(".uno:Delete"));
3028 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:FillDown"));
3029 xScAccel->setKeyEvent(aAltDown, OUString(".uno:DataSelect"));
3030 break;
3031 case ScOptionsUtil::KEY_OOO_LEGACY:
3032 xScAccel->setKeyEvent(aDelete, OUString(".uno:Delete"));
3033 xScAccel->setKeyEvent(aBackspace, OUString(".uno:ClearContents"));
3034 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:DataSelect"));
3035 break;
3036 default:
3040 xScAccel->store();
3043 void ScDocShell::UseSheetSaveEntries()
3045 if (pSheetSaveData)
3047 pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
3049 bool bHasEntries = false;
3050 SCTAB nTabCount = aDocument.GetTableCount();
3051 SCTAB nTab;
3052 for (nTab = 0; nTab < nTabCount; ++nTab)
3053 if (pSheetSaveData->HasStreamPos(nTab))
3054 bHasEntries = true;
3056 if (!bHasEntries)
3058 // if no positions were set (for example, export to other format),
3059 // reset all "valid" flags
3061 for (nTab = 0; nTab < nTabCount; ++nTab)
3062 if (aDocument.IsStreamValid(nTab))
3063 aDocument.SetStreamValid(nTab, false);
3068 // --- ScDocShellModificator ------------------------------------------
3070 ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
3072 rDocShell( rDS ),
3073 mpProtector(new ScRefreshTimerProtector(rDS.GetDocument()->GetRefreshTimerControlAddress()))
3075 ScDocument* pDoc = rDocShell.GetDocument();
3076 bAutoCalcShellDisabled = pDoc->IsAutoCalcShellDisabled();
3077 bIdleEnabled = pDoc->IsIdleEnabled();
3078 pDoc->SetAutoCalcShellDisabled( true );
3079 pDoc->EnableIdle(false);
3083 ScDocShellModificator::~ScDocShellModificator()
3085 ScDocument* pDoc = rDocShell.GetDocument();
3086 pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3087 if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
3088 rDocShell.SetDocumentModified(); // last one shuts off the lights
3089 pDoc->EnableIdle(bIdleEnabled);
3093 void ScDocShellModificator::SetDocumentModified()
3095 ScDocument* pDoc = rDocShell.GetDocument();
3096 pDoc->ClearFormulaContext();
3097 if ( !pDoc->IsImportingXML() )
3099 // AutoCalcShellDisabled temporaer restaurieren
3100 bool bDisabled = pDoc->IsAutoCalcShellDisabled();
3101 pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3102 rDocShell.SetDocumentModified();
3103 pDoc->SetAutoCalcShellDisabled( bDisabled );
3105 else
3107 // uno broadcast is necessary for api to work
3108 // -> must also be done during xml import
3109 pDoc->BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
3113 bool ScDocShell::IsChangeRecording() const
3115 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3116 return pChangeTrack != NULL;
3120 bool ScDocShell::HasChangeRecordProtection() const
3122 bool bRes = false;
3123 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3124 if (pChangeTrack)
3125 bRes = pChangeTrack->IsProtected();
3126 return bRes;
3130 void ScDocShell::SetChangeRecording( bool bActivate )
3132 bool bOldChangeRecording = IsChangeRecording();
3134 if (bActivate)
3136 aDocument.StartChangeTracking();
3137 ScChangeViewSettings aChangeViewSet;
3138 aChangeViewSet.SetShowChanges(true);
3139 aDocument.SetChangeViewSettings(aChangeViewSet);
3141 else
3143 aDocument.EndChangeTracking();
3144 PostPaintGridAll();
3147 if (bOldChangeRecording != IsChangeRecording())
3149 UpdateAcceptChangesDialog();
3150 // Slots invalidieren
3151 SfxBindings* pBindings = GetViewBindings();
3152 if (pBindings)
3153 pBindings->InvalidateAll(false);
3158 bool ScDocShell::SetProtectionPassword( const OUString &rNewPassword )
3160 bool bRes = false;
3161 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3162 if (pChangeTrack)
3164 bool bProtected = pChangeTrack->IsProtected();
3166 if (!rNewPassword.isEmpty())
3168 // when password protection is applied change tracking must always be active
3169 SetChangeRecording( true );
3171 ::com::sun::star::uno::Sequence< sal_Int8 > aProtectionHash;
3172 SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword );
3173 pChangeTrack->SetProtection( aProtectionHash );
3175 else
3177 pChangeTrack->SetProtection( ::com::sun::star::uno::Sequence< sal_Int8 >() );
3179 bRes = true;
3181 if ( bProtected != pChangeTrack->IsProtected() )
3183 UpdateAcceptChangesDialog();
3184 SetDocumentModified();
3188 return bRes;
3192 bool ScDocShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > &rPasswordHash )
3194 bool bRes = false;
3195 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3196 if (pChangeTrack && pChangeTrack->IsProtected())
3198 rPasswordHash = pChangeTrack->GetProtection();
3199 bRes = true;
3201 return bRes;
3204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */