Stop leaking all ScPostIt instances.
[LibreOffice.git] / sc / source / ui / docshell / docsh.cxx
blobb4cf615ca227bf3c6c56003fa24012e43cc9da9c
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 <svl/documentlockfile.hxx>
38 #include <svl/sharecontrolfile.hxx>
39 #include "svl/urihelper.hxx"
40 #include "chgtrack.hxx"
41 #include "chgviset.hxx"
42 #include <com/sun/star/awt/Key.hpp>
43 #include <com/sun/star/awt/KeyModifier.hpp>
44 #include <com/sun/star/container/XContentEnumerationAccess.hpp>
45 #include <com/sun/star/document/UpdateDocMode.hpp>
46 #include <com/sun/star/script/vba/VBAEventId.hpp>
47 #include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
48 #include <com/sun/star/sheet/XSpreadsheetView.hpp>
49 #include <com/sun/star/task/XJob.hpp>
50 #include <com/sun/star/ui/ModuleUIConfigurationManagerSupplier.hpp>
51 #include <com/sun/star/ui/XAcceleratorConfiguration.hpp>
52 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
53 #include <com/sun/star/sheet/XSpreadsheet.hpp>
54 #include <com/sun/star/container/XIndexAccess.hpp>
55 #include <com/sun/star/table/XTableChartsSupplier.hpp>
56 #include <com/sun/star/table/XTableCharts.hpp>
57 #include <com/sun/star/table/XTableChart.hpp>
58 #include <com/sun/star/chart2/XChartDocument.hpp>
59 #include <com/sun/star/document/XEmbeddedObjectSupplier.hpp>
60 #include <com/sun/star/frame/XStorable2.hpp>
61 #include <com/sun/star/frame/Desktop.hpp>
63 #include "scabstdlg.hxx"
64 #include <sot/formats.hxx>
66 #include "formulacell.hxx"
67 #include "postit.hxx"
68 #include "global.hxx"
69 #include "filter.hxx"
70 #include "scmod.hxx"
71 #include "tabvwsh.hxx"
72 #include "docfunc.hxx"
73 #include "imoptdlg.hxx"
74 #include "impex.hxx"
75 #include "scresid.hxx"
76 #include "sc.hrc"
77 #include "globstr.hrc"
78 #include "scerrors.hxx"
79 #include "brdcst.hxx"
80 #include "stlpool.hxx"
81 #include "autostyl.hxx"
82 #include "attrib.hxx"
83 #include "asciiopt.hxx"
84 #include "waitoff.hxx"
85 #include "docpool.hxx"
86 #include "progress.hxx"
87 #include "pntlock.hxx"
88 #include "docuno.hxx"
89 #include "appoptio.hxx"
90 #include "detdata.hxx"
91 #include "printfun.hxx"
92 #include "dociter.hxx"
93 #include "cellform.hxx"
94 #include "chartlis.hxx"
95 #include "hints.hxx"
96 #include "xmlwrap.hxx"
97 #include "drwlayer.hxx"
98 #include "refreshtimer.hxx"
99 #include "dbdata.hxx"
100 #include "scextopt.hxx"
101 #include "compiler.hxx"
102 #include "cfgids.hxx"
103 #include "warnpassword.hxx"
104 #include "optsolver.hxx"
105 #include "sheetdata.hxx"
106 #include "tabprotection.hxx"
107 #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>
125 #include <config_telepathy.h>
127 #if ENABLE_TELEPATHY
128 #include "sccollaboration.hxx"
129 #endif
131 #include <vector>
132 #include <boost/shared_ptr.hpp>
134 using namespace com::sun::star;
135 using ::com::sun::star::uno::Reference;
136 using ::com::sun::star::uno::UNO_QUERY;
137 using ::com::sun::star::lang::XMultiServiceFactory;
138 using ::boost::shared_ptr;
139 using ::std::vector;
141 // STATIC DATA -----------------------------------------------------------
143 // Filter-Namen (wie in sclib.cxx)
145 static const sal_Char pFilterSc50[] = "StarCalc 5.0";
146 static const sal_Char pFilterSc40[] = "StarCalc 4.0";
147 static const sal_Char pFilterSc30[] = "StarCalc 3.0";
148 static const sal_Char pFilterSc10[] = "StarCalc 1.0";
149 static const sal_Char pFilterXML[] = "StarOffice XML (Calc)";
150 static const sal_Char pFilterAscii[] = "Text - txt - csv (StarCalc)";
151 static const sal_Char pFilterLotus[] = "Lotus";
152 static const sal_Char pFilterQPro6[] = "Quattro Pro 6.0";
153 static const sal_Char pFilterExcel4[] = "MS Excel 4.0";
154 static const sal_Char pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
155 static const sal_Char pFilterExcel5[] = "MS Excel 5.0/95";
156 static const sal_Char pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
157 static const sal_Char pFilterExcel95[] = "MS Excel 95";
158 static const sal_Char pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
159 static const sal_Char pFilterExcel97[] = "MS Excel 97";
160 static const sal_Char pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
161 static const sal_Char pFilterDBase[] = "dBase";
162 static const sal_Char pFilterDif[] = "DIF";
163 static const sal_Char pFilterSylk[] = "SYLK";
164 static const sal_Char pFilterHtml[] = "HTML (StarCalc)";
165 static const sal_Char pFilterHtmlWebQ[] = "calc_HTML_WebQuery";
166 static const sal_Char pFilterRtf[] = "Rich Text Format (StarCalc)";
168 //----------------------------------------------------------------------
170 #define ScDocShell
171 #include "scslots.hxx"
174 SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell, ScResId(SCSTR_DOCSHELL))
178 // GlobalName der aktuellen Version:
179 SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "scalc" )
181 TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: kein Type-Info ?
183 //------------------------------------------------------------------
185 void ScDocShell::FillClass( SvGlobalName* pClassName,
186 sal_uInt32* pFormat,
187 OUString* /* pAppName */,
188 OUString* pFullTypeName,
189 OUString* pShortTypeName,
190 sal_Int32 nFileFormat,
191 sal_Bool bTemplate /* = sal_False */) const
193 if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
195 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
196 *pFormat = SOT_FORMATSTR_ID_STARCALC_60;
197 *pFullTypeName = OUString( ScResId( SCSTR_LONG_SCDOC_NAME ) );
198 *pShortTypeName = OUString( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
200 else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
202 *pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
203 *pFormat = bTemplate ? SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : SOT_FORMATSTR_ID_STARCALC_8;
204 *pFullTypeName = "calc8";
205 *pShortTypeName = ScResId(SCSTR_SHORT_SCDOC_NAME).toString();
207 else
209 OSL_FAIL("wat fuer ne Version?");
213 //------------------------------------------------------------------
215 void ScDocShell::DoEnterHandler()
217 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
218 if (pViewSh)
219 if (pViewSh->GetViewData()->GetDocShell() == this)
220 SC_MOD()->InputEnterHandler();
223 //------------------------------------------------------------------
225 SCTAB ScDocShell::GetSaveTab()
227 SCTAB nTab = 0;
228 ScTabViewShell* pSh = GetBestViewShell();
229 if (pSh)
231 const ScMarkData& rMark = pSh->GetViewData()->GetMarkData();
232 nTab = rMark.GetFirstSelected();
234 return nTab;
237 sal_uInt16 ScDocShell::GetHiddenInformationState( sal_uInt16 nStates )
239 // get global state like HIDDENINFORMATION_DOCUMENTVERSIONS
240 sal_uInt16 nState = SfxObjectShell::GetHiddenInformationState( nStates );
242 if ( nStates & HIDDENINFORMATION_RECORDEDCHANGES )
244 if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
245 nState |= HIDDENINFORMATION_RECORDEDCHANGES;
247 if ( nStates & HIDDENINFORMATION_NOTES )
249 SCTAB nTableCount = aDocument.GetTableCount();
250 bool bFound = false;
251 for (SCTAB nTab = 0; nTab < nTableCount && !bFound; ++nTab)
253 if (aDocument.HasTabNotes(nTab)) //TODO:
254 bFound = true;
257 if (bFound)
258 nState |= HIDDENINFORMATION_NOTES;
261 return nState;
264 void ScDocShell::BeforeXMLLoading()
266 aDocument.EnableIdle(false);
268 // prevent unnecessary broadcasts and updates
269 OSL_ENSURE(pModificator == NULL, "The Modificator should not exist");
270 pModificator = new ScDocShellModificator( *this );
272 aDocument.SetImportingXML( sal_True );
273 aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
274 aDocument.EnableUndo( false );
275 // prevent unnecessary broadcasts and "half way listeners"
276 aDocument.SetInsertingFromOtherDoc( sal_True );
279 void ScDocShell::AfterXMLLoading(sal_Bool bRet)
281 if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
283 UpdateLinks();
284 // don't prevent establishing of listeners anymore
285 aDocument.SetInsertingFromOtherDoc( false );
286 if ( bRet )
288 ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
289 if (pChartListener)
290 pChartListener->UpdateDirtyCharts();
292 // #95582#; set the table names of linked tables to the new path
293 SCTAB nTabCount = aDocument.GetTableCount();
294 for (SCTAB i = 0; i < nTabCount; ++i)
296 if (aDocument.IsLinked( i ))
298 OUString aName;
299 aDocument.GetName(i, aName);
300 OUString aLinkTabName = aDocument.GetLinkTab(i);
301 sal_Int32 nLinkTabNameLength = aLinkTabName.getLength();
302 sal_Int32 nNameLength = aName.getLength();
303 if (nLinkTabNameLength < nNameLength)
306 // remove the quottes on begin and end of the docname and restore the escaped quotes
307 const sal_Unicode* pNameBuffer = aName.getStr();
308 if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
309 ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
311 OUStringBuffer aDocURLBuffer;
312 sal_Bool bQuote = sal_True; // Dokumentenname ist immer quoted
313 ++pNameBuffer;
314 while ( bQuote && *pNameBuffer )
316 if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
317 bQuote = false;
318 else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
319 aDocURLBuffer.append(*pNameBuffer); // falls escaped Quote: nur Quote in den Namen
320 ++pNameBuffer;
324 if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
326 xub_StrLen nIndex = nNameLength - nLinkTabNameLength;
327 INetURLObject aINetURLObject(aDocURLBuffer.makeStringAndClear());
328 if(aName == aLinkTabName.copy(nIndex, nLinkTabNameLength) &&
329 (aName[nIndex - 1] == '#') && // before the table name should be the # char
330 !aINetURLObject.HasError()) // the docname should be a valid URL
332 aName = ScGlobal::GetDocTabName( aDocument.GetLinkDoc( i ), aDocument.GetLinkTab( i ) );
333 aDocument.RenameTab(i, aName, sal_True, sal_True);
335 // else; nothing has to happen, because it is a user given name
337 // else; nothing has to happen, because it is a user given name
339 // else; nothing has to happen, because it is a user given name
341 // else; nothing has to happen, because it is a user given name
345 // #i94570# DataPilot table names have to be unique, or the tables can't be accessed by API.
346 // If no name (or an invalid name, skipped in ScXMLDataPilotTableContext::EndElement) was set, create a new name.
347 ScDPCollection* pDPCollection = aDocument.GetDPCollection();
348 if ( pDPCollection )
350 size_t nDPCount = pDPCollection->GetCount();
351 for (size_t nDP=0; nDP<nDPCount; ++nDP)
353 ScDPObject* pDPObj = (*pDPCollection)[nDP];
354 if (pDPObj->GetName().isEmpty())
355 pDPObj->SetName( pDPCollection->CreateNewName() );
360 else
361 aDocument.SetInsertingFromOtherDoc( false );
363 aDocument.SetImportingXML( false );
364 aDocument.EnableExecuteLink( true );
365 aDocument.EnableUndo( sal_True );
366 bIsEmpty = false;
368 if (pModificator)
370 bool bRecalcState = aDocument.GetHardRecalcState();
371 //temporarily set hard-recalc to prevent calling ScFormulaCell::Notify()
372 //which will set the cells dirty.
373 aDocument.SetHardRecalcState(true);
374 delete pModificator;
375 aDocument.SetHardRecalcState(bRecalcState);
376 pModificator = NULL;
378 else
380 OSL_FAIL("The Modificator should exist");
383 aDocument.EnableIdle(true);
386 namespace {
388 class LoadMediumGuard
390 public:
391 explicit LoadMediumGuard(ScDocument* pDoc) :
392 mpDoc(pDoc)
394 mpDoc->SetLoadingMedium(true);
397 ~LoadMediumGuard()
399 mpDoc->SetLoadingMedium(false);
401 private:
402 ScDocument* mpDoc;
405 void processDataStream( ScDocShell& rShell, const sc::ImportPostProcessData& rData )
407 if (!rData.mpDataStream)
408 return;
410 const sc::ImportPostProcessData::DataStream& r = *rData.mpDataStream;
411 if (!r.maRange.IsValid())
412 return;
414 // Break the streamed range into the top range and the height limit. A
415 // height limit of 0 means unlimited i.e. the streamed data will go all
416 // the way to the last row.
418 ScRange aTopRange = r.maRange;
419 aTopRange.aEnd.SetRow(aTopRange.aStart.Row());
420 sal_Int32 nLimit = r.maRange.aEnd.Row() - r.maRange.aStart.Row() + 1;
421 if (r.maRange.aEnd.Row() == MAXROW)
422 // Unlimited range.
423 nLimit = 0;
425 sc::DataStream::MoveType eMove =
426 r.meInsertPos == sc::ImportPostProcessData::DataStream::InsertTop ?
427 sc::DataStream::MOVE_DOWN : sc::DataStream::RANGE_DOWN;
429 sc::DataStream* pStrm = new sc::DataStream(&rShell, r.maURL, aTopRange, nLimit, eMove, 0);
430 pStrm->SetRefreshOnEmptyLine(r.mbRefreshOnEmpty);
431 sc::DocumentLinkManager& rMgr = rShell.GetDocument()->GetDocLinkManager();
432 rMgr.setDataStream(pStrm);
437 sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
439 LoadMediumGuard aLoadGuard(&aDocument);
441 // MacroCallMode is no longer needed, state is kept in SfxObjectShell now
443 // no Seek(0) here - always loading from storage, GetInStream must not be called
445 BeforeXMLLoading();
447 // #i62677# BeforeXMLLoading is also called from ScXMLImport::startDocument when invoked
448 // from an external component. The XMLFromWrapper flag is only set here, when called
449 // through ScDocShell.
450 aDocument.SetXMLFromWrapper( sal_True );
452 ScXMLImportWrapper aImport( aDocument, pLoadMedium, xStor );
454 sal_Bool bRet(false);
455 ErrCode nError = ERRCODE_NONE;
456 aDocument.EnableAdjustHeight(false);
457 if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
458 bRet = aImport.Import(false, nError);
459 else
460 bRet = aImport.Import(sal_True, nError);
462 if ( nError )
463 pLoadMedium->SetError( nError, OUString( OSL_LOG_PREFIX ) );
465 processDataStream(*this, aImport.GetImportPostProcessData());
467 //if the document was not generated by LibreOffice, do hard recalc in case some other document
468 //generator saved cached formula results that differ from LibreOffice's calculated results or
469 //did not use cached formula results.
470 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(GetModel(), uno::UNO_QUERY_THROW);
471 uno::Reference<document::XDocumentProperties> xDocProps = xDPS->getDocumentProperties();
473 Reference<uno::XComponentContext> xContext = comphelper::getProcessComponentContext();
474 ScRecalcOptions nRecalcMode =
475 static_cast<ScRecalcOptions>(officecfg::Office::Calc::Formula::Load::ODFRecalcMode::get(xContext));
477 bool bHardRecalc = false;
478 if (nRecalcMode == RECALC_ASK)
480 OUString sProductName(utl::ConfigManager::getProductName());
481 if (aDocument.IsUserInteractionEnabled() && xDocProps->getGenerator().indexOf(sProductName) == -1)
483 // Generator is not LibreOffice. Ask if the user wants to perform
484 // full re-calculation.
485 QueryBox aBox(
486 GetActiveDialogParent(), WinBits(WB_YES_NO | WB_DEF_YES),
487 ScGlobal::GetRscString(STR_QUERY_FORMULA_RECALC_ONLOAD_ODS));
488 aBox.SetCheckBoxText(ScGlobal::GetRscString(STR_ALWAYS_PERFORM_SELECTED));
490 bHardRecalc = aBox.Execute() == RET_YES;
492 if (aBox.GetCheckBoxState())
494 // Always perform selected action in the future.
495 boost::shared_ptr< comphelper::ConfigurationChanges > batch( comphelper::ConfigurationChanges::create() );
496 officecfg::Office::Calc::Formula::Load::ODFRecalcMode::set(sal_Int32(0), batch);
497 ScFormulaOptions aOpt = SC_MOD()->GetFormulaOptions();
498 aOpt.SetODFRecalcOptions(bHardRecalc ? RECALC_ALWAYS : RECALC_NEVER);
499 SC_MOD()->SetFormulaOptions(aOpt);
501 batch->commit();
505 else if (nRecalcMode == RECALC_ALWAYS)
506 bHardRecalc = true;
508 if (bHardRecalc)
509 DoHardRecalc(false);
510 else
512 // still need to recalc volatile formula cells.
513 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
516 aDocument.SetXMLFromWrapper( false );
517 AfterXMLLoading(bRet);
519 aDocument.EnableAdjustHeight(true);
520 return bRet;
523 sal_Bool ScDocShell::SaveXML( SfxMedium* pSaveMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
525 aDocument.EnableIdle(false);
527 ScXMLImportWrapper aImport( aDocument, pSaveMedium, xStor );
528 sal_Bool bRet(false);
529 if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
530 bRet = aImport.Export(false);
531 else
532 bRet = aImport.Export(sal_True);
534 aDocument.EnableIdle(true);
536 return bRet;
539 bool ScDocShell::SaveCurrentChart( SfxMedium& rMedium )
541 bool bRet = false;
546 uno::Reference< lang::XComponent > xCurrentComponent = frame::Desktop::create( comphelper::getProcessComponentContext() )->getCurrentComponent();
548 uno::Reference< frame::XStorable2 > xStorable( xCurrentComponent, uno::UNO_QUERY_THROW );
550 uno::Reference< frame::XModel > xChartDoc ( xCurrentComponent, uno::UNO_QUERY_THROW );
552 ScXMLChartExportWrapper aExport( xChartDoc, rMedium );
553 bRet = aExport.Export();
555 catch(...)
557 SAL_WARN("sc", "exception thrown while saving chart. Bug!!!");
559 return bRet;
562 sal_Bool ScDocShell::Load( SfxMedium& rMedium )
564 LoadMediumGuard aLoadGuard(&aDocument);
565 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
567 // only the latin script language is loaded
568 // -> initialize the others from options (before loading)
569 InitOptions(true);
571 GetUndoManager()->Clear();
573 sal_Bool bRet = SfxObjectShell::Load( rMedium );
574 if( bRet )
576 if (GetMedium())
578 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
579 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
583 // prepare a valid document for XML filter
584 // (for ConvertFrom, InitNew is called before)
585 aDocument.MakeTable(0);
586 aDocument.GetStyleSheetPool()->CreateStandardStyles();
587 aDocument.UpdStlShtPtrsFrmNms();
589 bRet = LoadXML( &rMedium, NULL );
593 if (!bRet && !rMedium.GetError())
594 rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, OUString( OSL_LOG_PREFIX ) );
596 if (rMedium.GetError())
597 SetError( rMedium.GetError(), OUString( OSL_LOG_PREFIX ) );
599 InitItems();
600 CalcOutputFactor();
602 // invalidate eventually temporary table areas
603 if ( bRet )
604 aDocument.InvalidateTableArea();
606 bIsEmpty = false;
607 FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
608 return bRet;
611 void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
613 if (rHint.ISA(ScTablesHint) )
615 const ScTablesHint& rScHint = static_cast< const ScTablesHint& >( rHint );
616 if (rScHint.GetId() == SC_TAB_INSERTED)
618 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor();
619 if ( xVbaEvents.is() ) try
621 uno::Sequence< uno::Any > aArgs( 1 );
622 aArgs[0] <<= rScHint.GetTab1();
623 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs );
625 catch( uno::Exception& )
631 if (rHint.ISA(SfxSimpleHint)) // ohne Parameter
633 sal_uLong nSlot = ((const SfxSimpleHint&)rHint).GetId();
634 switch ( nSlot )
636 case SFX_HINT_TITLECHANGED:
637 aDocument.SetName( SfxShell::GetName() );
638 // RegisterNewTargetNames gibts nicht mehr
639 SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
640 break;
643 else if (rHint.ISA(SfxStyleSheetHint)) // Vorlagen geaendert
644 NotifyStyle((const SfxStyleSheetHint&) rHint);
645 else if (rHint.ISA(ScAutoStyleHint))
647 //! direct call for AutoStyles
649 // this is called synchronously from ScInterpreter::ScStyle,
650 // modifying the document must be asynchronous
651 // (handled by AddInitial)
653 ScAutoStyleHint& rStlHint = (ScAutoStyleHint&)rHint;
654 ScRange aRange = rStlHint.GetRange();
655 OUString aName1 = rStlHint.GetStyle1();
656 OUString aName2 = rStlHint.GetStyle2();
657 sal_uInt32 nTimeout = rStlHint.GetTimeout();
659 if (!pAutoStyleList)
660 pAutoStyleList = new ScAutoStyleList(this);
661 pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 );
663 else if ( rHint.ISA( SfxEventHint ) )
665 sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
666 switch ( nEventId )
668 case SFX_EVENT_LOADFINISHED:
670 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
671 // the readonly documents should not be opened in shared mode
672 if ( HasSharedXMLFlagSet() && !SC_MOD()->IsInSharedDocLoading() && !IsReadOnly() )
674 if ( SwitchToShared( sal_True, false ) )
676 ScViewData* pViewData = GetViewData();
677 ScTabView* pTabView = ( pViewData ? dynamic_cast< ScTabView* >( pViewData->GetView() ) : NULL );
678 if ( pTabView )
680 pTabView->UpdateLayerLocks();
683 else
685 // switching to shared mode has failed, the document should be opened readonly
686 // TODO/LATER: And error message should be shown here probably
687 SetReadOnlyUI( sal_True );
690 #endif
692 break;
693 case SFX_EVENT_VIEWCREATED:
695 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
696 if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() )
698 ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
699 if ( aAppOptions.GetShowSharedDocumentWarning() )
701 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
702 ScGlobal::GetRscString( STR_SHARED_DOC_WARNING ) );
703 aBox.SetDefaultCheckBoxText();
704 aBox.Execute();
705 sal_Bool bChecked = aBox.GetCheckBoxState();
706 if ( bChecked )
708 aAppOptions.SetShowSharedDocumentWarning( !bChecked );
709 SC_MOD()->SetAppOptions( aAppOptions );
713 #endif
716 uno::Reference< uno::XComponentContext > xContext(
717 comphelper::getProcessComponentContext() );
718 uno::Reference< lang::XMultiServiceFactory > xServiceManager(
719 xContext->getServiceManager(),
720 uno::UNO_QUERY_THROW );
721 uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xServiceManager, uno::UNO_QUERY_THROW );
722 uno::Reference< container::XEnumeration> xEnum = xEnumAccess->createContentEnumeration(
723 OUString( "com.sun.star.sheet.SpreadsheetDocumentJob" ) );
724 if ( xEnum.is() )
726 while ( xEnum->hasMoreElements() )
728 uno::Any aAny = xEnum->nextElement();
729 uno::Reference< lang::XSingleComponentFactory > xFactory;
730 aAny >>= xFactory;
731 if ( xFactory.is() )
733 uno::Reference< task::XJob > xJob( xFactory->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
734 uno::Sequence< beans::NamedValue > aArgsForJob(1);
735 ScViewData* pViewData = GetViewData();
736 SfxViewShell* pViewShell = ( pViewData ? pViewData->GetViewShell() : NULL );
737 SfxViewFrame* pViewFrame = ( pViewShell ? pViewShell->GetViewFrame() : NULL );
738 SfxFrame* pFrame = ( pViewFrame ? &pViewFrame->GetFrame() : NULL );
739 uno::Reference< frame::XController > xController = ( pFrame ? pFrame->GetController() : 0 );
740 uno::Reference< sheet::XSpreadsheetView > xSpreadsheetView( xController, uno::UNO_QUERY_THROW );
741 aArgsForJob[0] = beans::NamedValue( OUString( "SpreadsheetView" ),
742 uno::makeAny( xSpreadsheetView ) );
743 xJob->execute( aArgsForJob );
748 catch ( uno::Exception & )
752 break;
753 case SFX_EVENT_SAVEDOC:
755 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
756 if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
758 bool bSuccess = false;
759 bool bRetry = true;
760 while ( bRetry )
762 bRetry = false;
763 uno::Reference< frame::XModel > xModel;
766 // load shared file
767 xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
768 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
770 // check if shared flag is set in shared file
771 bool bShared = false;
772 ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
773 ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : NULL );
774 if ( pSharedDocShell )
776 bShared = pSharedDocShell->HasSharedXMLFlagSet();
779 // #i87870# check if shared status was disabled and enabled again
780 bool bOwnEntry = false;
781 bool bEntriesNotAccessible = false;
784 ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
785 bOwnEntry = aControlFile.HasOwnEntry();
787 catch ( uno::Exception& )
789 bEntriesNotAccessible = true;
792 if ( bShared && bOwnEntry )
794 uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
796 if ( xStorable->isReadonly() )
798 xCloseable->close( sal_True );
800 OUString aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
801 bool bNoLockAccess = false;
804 ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
805 uno::Sequence< OUString > aData = aLockFile.GetLockData();
806 if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
808 if ( !aData[LOCKFILE_OOOUSERNAME_ID].isEmpty() )
810 aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
812 else if ( !aData[LOCKFILE_SYSUSERNAME_ID].isEmpty() )
814 aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
818 catch ( uno::Exception& )
820 bNoLockAccess = true;
823 if ( bNoLockAccess )
825 // TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
826 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
828 else
830 OUString aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
831 aMessage = aMessage.replaceFirst( "%1", aUserName );
833 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
834 if ( aBox.Execute() == RET_RETRY )
836 bRetry = true;
840 else
842 // merge changes from shared file into temp file
843 bool bSaveToShared = false;
844 if ( pSharedDocShell )
846 bSaveToShared = MergeSharedDocument( pSharedDocShell );
849 // close shared file
850 xCloseable->close( sal_True );
852 // TODO: keep file lock on shared file
854 // store to shared file
855 if ( bSaveToShared )
857 bool bChangedViewSettings = false;
858 ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
859 if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
861 pChangeViewSet->SetShowChanges( false );
862 pChangeViewSet->SetShowAccepted( false );
863 aDocument.SetChangeViewSettings( *pChangeViewSet );
864 bChangedViewSettings = true;
867 uno::Reference< frame::XStorable > xStor( GetModel(), uno::UNO_QUERY_THROW );
868 // TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
869 uno::Sequence< beans::PropertyValue > aValues(1);
870 aValues[0].Name = "FilterName";
871 aValues[0].Value <<= OUString( GetMedium()->GetFilter()->GetFilterName() );
873 SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, false);
874 if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
876 aValues.realloc( 2 );
877 aValues[1].Name = "Password";
878 aValues[1].Value <<= pPasswordItem->GetValue();
881 SC_MOD()->SetInSharedDocSaving( true );
882 xStor->storeToURL( GetSharedFileURL(), aValues );
883 SC_MOD()->SetInSharedDocSaving( false );
885 if ( bChangedViewSettings )
887 pChangeViewSet->SetShowChanges( sal_True );
888 pChangeViewSet->SetShowAccepted( sal_True );
889 aDocument.SetChangeViewSettings( *pChangeViewSet );
893 bSuccess = true;
894 GetUndoManager()->Clear();
897 else
899 xCloseable->close( sal_True );
901 if ( bEntriesNotAccessible )
903 // TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
904 ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
906 else
908 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
909 ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
910 aBox.Execute();
912 SfxBindings* pBindings = GetViewBindings();
913 if ( pBindings )
915 pBindings->ExecuteSynchron( SID_SAVEASDOC );
920 catch ( uno::Exception& )
922 OSL_FAIL( "SFX_EVENT_SAVEDOC: caught exception\n" );
923 SC_MOD()->SetInSharedDocSaving( false );
927 uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
928 xClose->close( sal_True );
930 catch ( uno::Exception& )
936 if ( !bSuccess )
937 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
939 #endif
941 if (pSheetSaveData)
942 pSheetSaveData->SetInSupportedSave(true);
944 break;
945 case SFX_EVENT_SAVEASDOC:
947 if ( GetDocument()->GetExternalRefManager()->containsUnsavedReferences() )
949 WarningBox aBox( GetActiveDialogParent(), WinBits( WB_YES_NO ),
950 ScGlobal::GetRscString( STR_UNSAVED_EXT_REF ) );
952 if( RET_NO == aBox.Execute())
954 SetError( ERRCODE_IO_ABORT, OUString( OSL_LOG_PREFIX ) ); // this error code will produce no error message, but will break the further saving process
957 } // fall through
958 case SFX_EVENT_SAVETODOC:
959 // #i108978# If no event is sent before saving, there will also be no "...DONE" event,
960 // and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
961 // if there is a SAVE/SAVEAS/SAVETO event first.
962 if (pSheetSaveData)
963 pSheetSaveData->SetInSupportedSave(true);
964 break;
965 case SFX_EVENT_SAVEDOCDONE:
966 case SFX_EVENT_SAVEASDOCDONE:
968 // new positions are used after "save" and "save as", but not "save to"
969 UseSheetSaveEntries(); // use positions from saved file for next saving
970 } // fall through
971 case SFX_EVENT_SAVETODOCDONE:
972 // only reset the flag, don't use the new positions
973 if (pSheetSaveData)
974 pSheetSaveData->SetInSupportedSave(false);
975 break;
976 default:
979 break;
984 // Inhalte fuer Organizer laden
987 sal_Bool ScDocShell::LoadFrom( SfxMedium& rMedium )
989 LoadMediumGuard aLoadGuard(&aDocument);
990 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
992 WaitObject aWait( GetActiveDialogParent() );
994 sal_Bool bRet = false;
996 if (GetMedium())
998 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
999 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
1002 // until loading/saving only the styles in XML is implemented,
1003 // load the whole file
1004 bRet = LoadXML( &rMedium, NULL );
1005 InitItems();
1007 SfxObjectShell::LoadFrom( rMedium );
1009 return bRet;
1012 static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert)
1014 OUStringBuffer aBuf;
1015 std::vector< OUString > aTokens;
1016 sal_Int32 n = rOption.getLength();
1017 const sal_Unicode* p = rOption.getStr();
1018 for (sal_Int32 i = 0; i < n; ++i)
1020 const sal_Unicode c = p[i];
1021 if (c == ' ')
1023 if (!aBuf.isEmpty())
1024 aTokens.push_back( aBuf.makeStringAndClear() );
1026 else
1027 aBuf.append(c);
1030 if (!aBuf.isEmpty())
1031 aTokens.push_back( aBuf.makeStringAndClear() );
1033 rLang = LanguageType( 0 );
1034 rDateConvert = false;
1036 if (aTokens.size() > 0)
1037 rLang = static_cast<LanguageType>(aTokens[0].toInt32());
1038 if (aTokens.size() > 1)
1039 rDateConvert = static_cast<bool>(aTokens[1].toInt32());
1042 sal_Bool ScDocShell::ConvertFrom( SfxMedium& rMedium )
1044 LoadMediumGuard aLoadGuard(&aDocument);
1046 sal_Bool bRet = false; // sal_False heisst Benutzerabbruch !!
1047 // bei Fehler: Fehler am Stream setzen!!
1049 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1051 GetUndoManager()->Clear();
1053 // ob nach dem Import optimale Spaltenbreiten gesetzt werden sollen
1054 sal_Bool bSetColWidths = false;
1055 sal_Bool bSetSimpleTextColWidths = false;
1056 ScColWidthParam aColWidthParam[MAXCOLCOUNT];
1057 ScRange aColWidthRange;
1058 // ob nach dem Import optimale Zeilenhoehen gesetzt werden sollen
1059 sal_Bool bSetRowHeights = false;
1061 vector<ScDocRowHeightUpdater::TabRanges> aRecalcRowRangesArray;
1063 // Alle Filter brauchen die komplette Datei am Stueck (nicht asynchron),
1064 // darum vorher per CreateFileStream dafuer sorgen, dass die komplette
1065 // Datei uebertragen wird.
1066 rMedium.GetPhysicalName(); //! CreateFileStream direkt rufen, wenn verfuegbar
1068 SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, false);
1069 nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
1071 const SfxFilter* pFilter = rMedium.GetFilter();
1072 if (pFilter)
1074 OUString aFltName = pFilter->GetFilterName();
1076 sal_Bool bCalc3 = ( aFltName.equalsAscii(pFilterSc30) );
1077 sal_Bool bCalc4 = ( aFltName.equalsAscii(pFilterSc40) );
1078 if (!bCalc3 && !bCalc4)
1079 aDocument.SetInsertingFromOtherDoc( sal_True );
1081 if (aFltName.equalsAscii(pFilterXML))
1082 bRet = LoadXML( &rMedium, NULL );
1083 else if (aFltName.equalsAscii(pFilterSc10))
1085 SvStream* pStream = rMedium.GetInStream();
1086 if (pStream)
1088 FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
1089 if (eError != eERR_OK)
1091 if (!GetError())
1092 SetError(eError, OUString( OSL_LOG_PREFIX ));
1094 else
1095 bRet = sal_True;
1098 else if (aFltName.equalsAscii(pFilterLotus))
1100 OUString sItStr;
1101 SfxItemSet* pSet = rMedium.GetItemSet();
1102 const SfxPoolItem* pItem;
1103 if ( pSet && SFX_ITEM_SET ==
1104 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
1106 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1109 if (sItStr.isEmpty())
1111 // default for lotus import (from API without options):
1112 // IBM_437 encoding
1113 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
1116 FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
1117 ScGlobal::GetCharsetValue(sItStr));
1118 if (eError != eERR_OK)
1120 if (!GetError())
1121 SetError(eError, OUString( OSL_LOG_PREFIX ));
1123 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1124 bRet = sal_True;
1126 else
1127 bRet = sal_True;
1128 bSetColWidths = sal_True;
1129 bSetRowHeights = sal_True;
1131 else if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterExcel5) ||
1132 aFltName.equalsAscii(pFilterExcel95) || aFltName.equalsAscii(pFilterExcel97) ||
1133 aFltName.equalsAscii(pFilterEx4Temp) || aFltName.equalsAscii(pFilterEx5Temp) ||
1134 aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp) )
1136 EXCIMPFORMAT eFormat = EIF_AUTO;
1137 if ( aFltName.equalsAscii(pFilterExcel4) || aFltName.equalsAscii(pFilterEx4Temp) )
1138 eFormat = EIF_BIFF_LE4;
1139 else if ( aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
1140 aFltName.equalsAscii(pFilterEx5Temp) || aFltName.equalsAscii(pFilterEx95Temp) )
1141 eFormat = EIF_BIFF5;
1142 else if ( aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx97Temp) )
1143 eFormat = EIF_BIFF8;
1145 MakeDrawLayer(); //! im Filter
1146 CalcOutputFactor(); // prepare update of row height
1147 FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
1148 aDocument.UpdateFontCharSet();
1149 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
1150 aDocument.UpdateChartListenerCollection(); //! fuer alle Importe?
1152 // all graphics objects must have names
1153 aDocument.EnsureGraphicNames();
1155 if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
1157 if (!GetError())
1158 SetError(eError, OUString( OSL_LOG_PREFIX ));
1159 bRet = sal_True;
1161 else if (eError != eERR_OK)
1163 if (!GetError())
1164 SetError(eError, OUString( OSL_LOG_PREFIX ));
1166 else
1167 bRet = true;
1169 else if (aFltName.equalsAscii(pFilterAscii))
1171 SfxItemSet* pSet = rMedium.GetItemSet();
1172 const SfxPoolItem* pItem;
1173 ScAsciiOptions aOptions;
1174 sal_Bool bOptInit = false;
1176 if ( pSet && SFX_ITEM_SET ==
1177 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
1179 aOptions.ReadFromString( ((const SfxStringItem*)pItem)->GetValue() );
1180 bOptInit = sal_True;
1183 if ( !bOptInit )
1185 // default for ascii import (from API without options):
1186 // ISO8859-1/MS_1252 encoding, comma, double quotes
1188 aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
1189 aOptions.SetFieldSeps( OUString(',') );
1190 aOptions.SetTextSep( '"' );
1193 FltError eError = eERR_OK;
1194 bool bOverflowRow, bOverflowCol, bOverflowCell;
1195 bOverflowRow = bOverflowCol = bOverflowCell = false;
1197 if( ! rMedium.IsStorage() )
1199 ScImportExport aImpEx( &aDocument );
1200 aImpEx.SetExtOptions( aOptions );
1202 SvStream* pInStream = rMedium.GetInStream();
1203 if (pInStream)
1205 pInStream->SetStreamCharSet( aOptions.GetCharSet() );
1206 pInStream->Seek( 0 );
1207 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
1208 eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
1209 aDocument.StartAllListeners();
1210 aDocument.SetDirty();
1211 bOverflowRow = aImpEx.IsOverflowRow();
1212 bOverflowCol = aImpEx.IsOverflowCol();
1213 bOverflowCell = aImpEx.IsOverflowCell();
1215 else
1217 OSL_FAIL( "No Stream" );
1221 if (eError != eERR_OK)
1223 if (!GetError())
1224 SetError(eError, OUString( OSL_LOG_PREFIX ));
1226 else if (!GetError() && (bOverflowRow || bOverflowCol || bOverflowCell))
1228 // precedence: row, column, cell
1229 FltError nWarn = (bOverflowRow ? SCWARN_IMPORT_ROW_OVERFLOW :
1230 (bOverflowCol ? SCWARN_IMPORT_COLUMN_OVERFLOW :
1231 SCWARN_IMPORT_CELL_OVERFLOW));
1232 SetError( nWarn, OUString( OSL_LOG_PREFIX ));
1234 bSetColWidths = sal_True;
1235 bSetSimpleTextColWidths = sal_True;
1237 else if (aFltName.equalsAscii(pFilterDBase))
1239 OUString sItStr;
1240 SfxItemSet* pSet = rMedium.GetItemSet();
1241 const SfxPoolItem* pItem;
1242 if ( pSet && SFX_ITEM_SET ==
1243 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
1245 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1248 if (sItStr.isEmpty())
1250 // default for dBase import (from API without options):
1251 // IBM_850 encoding
1253 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
1256 ScDocRowHeightUpdater::TabRanges aRecalcRanges(0);
1257 sal_uLong eError = DBaseImport( rMedium.GetPhysicalName(),
1258 ScGlobal::GetCharsetValue(sItStr), aColWidthParam, *aRecalcRanges.mpRanges );
1259 aRecalcRowRangesArray.push_back(aRecalcRanges);
1261 if (eError != eERR_OK)
1263 if (!GetError())
1264 SetError(eError, OUString( OSL_LOG_PREFIX ));
1265 bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
1267 else
1268 bRet = sal_True;
1270 aColWidthRange.aStart.SetRow( 1 ); // Spaltenheader nicht
1271 bSetColWidths = true;
1272 bSetSimpleTextColWidths = true;
1274 else if (aFltName.equalsAscii(pFilterDif))
1276 SvStream* pStream = rMedium.GetInStream();
1277 if (pStream)
1279 FltError eError;
1280 OUString sItStr;
1281 SfxItemSet* pSet = rMedium.GetItemSet();
1282 const SfxPoolItem* pItem;
1283 if ( pSet && SFX_ITEM_SET ==
1284 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
1286 sItStr = ((const SfxStringItem*)pItem)->GetValue();
1289 if (sItStr.isEmpty())
1291 // default for DIF import (from API without options):
1292 // ISO8859-1/MS_1252 encoding
1294 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
1297 eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
1298 ScGlobal::GetCharsetValue(sItStr));
1299 if (eError != eERR_OK)
1301 if (!GetError())
1302 SetError(eError, OUString( OSL_LOG_PREFIX ));
1304 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1305 bRet = sal_True;
1307 else
1308 bRet = sal_True;
1310 bSetColWidths = sal_True;
1311 bSetSimpleTextColWidths = sal_True;
1312 bSetRowHeights = sal_True;
1314 else if (aFltName.equalsAscii(pFilterSylk))
1316 FltError eError = SCERR_IMPORT_UNKNOWN;
1317 if( !rMedium.IsStorage() )
1319 ScImportExport aImpEx( &aDocument );
1321 SvStream* pInStream = rMedium.GetInStream();
1322 if (pInStream)
1324 pInStream->Seek( 0 );
1325 bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SOT_FORMATSTR_ID_SYLK );
1326 eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
1327 aDocument.StartAllListeners();
1328 aDocument.SetDirty();
1330 else
1332 OSL_FAIL( "No Stream" );
1336 if ( eError != eERR_OK && !GetError() )
1337 SetError(eError, OUString( OSL_LOG_PREFIX ));
1338 bSetColWidths = sal_True;
1339 bSetSimpleTextColWidths = sal_True;
1340 bSetRowHeights = sal_True;
1342 else if (aFltName.equalsAscii(pFilterQPro6))
1344 FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
1345 if (eError != eERR_OK)
1347 if (!GetError())
1348 SetError( eError, OUString( OSL_LOG_PREFIX ) );
1349 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1350 bRet = sal_True;
1352 else
1353 bRet = sal_True;
1354 // TODO: Filter should set column widths. Not doing it here, it may
1355 // result in very narrow or wide columns, depending on content.
1356 // Setting row heights makes cells with font size attribution or
1357 // wrapping enabled look nicer..
1358 bSetRowHeights = sal_True;
1360 else if (aFltName.equalsAscii(pFilterRtf))
1362 FltError eError = SCERR_IMPORT_UNKNOWN;
1363 if( !rMedium.IsStorage() )
1365 SvStream* pInStream = rMedium.GetInStream();
1366 if (pInStream)
1368 pInStream->Seek( 0 );
1369 ScRange aRange;
1370 eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
1371 if (eError != eERR_OK)
1373 if (!GetError())
1374 SetError(eError, OUString( OSL_LOG_PREFIX ));
1376 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1377 bRet = sal_True;
1379 else
1380 bRet = sal_True;
1381 aDocument.StartAllListeners();
1382 aDocument.SetDirty();
1383 bSetColWidths = sal_True;
1384 bSetRowHeights = sal_True;
1386 else
1388 OSL_FAIL( "No Stream" );
1392 if ( eError != eERR_OK && !GetError() )
1393 SetError(eError, OUString( OSL_LOG_PREFIX ));
1395 else if (aFltName.equalsAscii(pFilterHtml) || aFltName.equalsAscii(pFilterHtmlWebQ))
1397 FltError eError = SCERR_IMPORT_UNKNOWN;
1398 sal_Bool bWebQuery = aFltName.equalsAscii(pFilterHtmlWebQ);
1399 if( !rMedium.IsStorage() )
1401 SvStream* pInStream = rMedium.GetInStream();
1402 if (pInStream)
1404 LanguageType eLang = LANGUAGE_SYSTEM;
1405 bool bDateConvert = false;
1406 SfxItemSet* pSet = rMedium.GetItemSet();
1407 const SfxPoolItem* pItem;
1408 if ( pSet && SFX_ITEM_SET ==
1409 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
1411 OUString aFilterOption = (static_cast<const SfxStringItem*>(pItem))->GetValue();
1412 lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert);
1415 pInStream->Seek( 0 );
1416 ScRange aRange;
1417 // HTML macht eigenes ColWidth/RowHeight
1418 CalcOutputFactor();
1419 SvNumberFormatter aNumFormatter( comphelper::getProcessComponentContext(), eLang);
1420 eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
1421 GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert );
1422 if (eError != eERR_OK)
1424 if (!GetError())
1425 SetError(eError, OUString( OSL_LOG_PREFIX ));
1427 if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
1428 bRet = sal_True;
1430 else
1431 bRet = sal_True;
1432 aDocument.StartAllListeners();
1433 aDocument.SetDirty();
1435 else
1437 OSL_FAIL( "No Stream" );
1441 if ( eError != eERR_OK && !GetError() )
1442 SetError(eError, OUString( OSL_LOG_PREFIX ));
1444 else
1446 if (!GetError())
1447 SetError(SCERR_IMPORT_NI, OUString( OSL_LOG_PREFIX ));
1450 if (!bCalc3)
1451 aDocument.SetInsertingFromOtherDoc( false );
1453 else
1455 OSL_FAIL("Kein Filter bei ConvertFrom");
1458 InitItems();
1459 CalcOutputFactor();
1460 if ( bRet && (bSetColWidths || bSetRowHeights) )
1461 { // Spaltenbreiten/Zeilenhoehen anpassen, Basis 100% Zoom
1462 Fraction aZoom( 1, 1 );
1463 double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom
1464 / GetOutputFactor(); // Faktor ist Drucker zu Bildschirm
1465 double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
1466 VirtualDevice aVirtDev;
1467 // all sheets (for Excel import)
1468 SCTAB nTabCount = aDocument.GetTableCount();
1469 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1471 SCCOL nEndCol;
1472 SCROW nEndRow;
1473 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1474 aColWidthRange.aEnd.SetCol( nEndCol );
1475 aColWidthRange.aEnd.SetRow( nEndRow );
1476 ScMarkData aMark;
1477 aMark.SetMarkArea( aColWidthRange );
1478 aMark.MarkToMulti();
1479 // Reihenfolge erst Breite dann Hoehe ist wichtig (vergl. hund.rtf)
1480 if ( bSetColWidths )
1482 for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
1484 if (!bSetSimpleTextColWidths)
1485 aColWidthParam[nCol].mbSimpleText = false;
1487 sal_uInt16 nWidth = aDocument.GetOptimalColWidth(
1488 nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoom, aZoom, false, &aMark,
1489 &aColWidthParam[nCol] );
1490 aDocument.SetColWidth( nCol, nTab,
1491 nWidth + (sal_uInt16)ScGlobal::nLastColWidthExtra );
1496 if (bSetRowHeights)
1498 // Update all rows in all tables.
1499 ScSizeDeviceProvider aProv(this);
1500 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), NULL);
1501 aUpdater.update();
1503 else if (!aRecalcRowRangesArray.empty())
1505 // Update only specified row ranges for better performance.
1506 ScSizeDeviceProvider aProv(this);
1507 ScDocRowHeightUpdater aUpdater(aDocument, aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), &aRecalcRowRangesArray);
1508 aUpdater.update();
1511 FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
1514 // invalidate eventually temporary table areas
1515 if ( bRet )
1516 aDocument.InvalidateTableArea();
1518 bIsEmpty = false;
1520 return bRet;
1523 bool ScDocShell::LoadExternal( SfxMedium& rMed )
1525 const SfxFilter* pFilter = rMed.GetFilter();
1526 if (!pFilter)
1527 return false;
1529 if (pFilter->GetProviderName() == "orcus")
1531 ScOrcusFilters* pOrcus = ScFormatFilter::Get().GetOrcusFilters();
1532 if (!pOrcus)
1533 return false;
1535 const OUString& rFilterName = pFilter->GetName();
1536 if (rFilterName == "gnumeric")
1538 if (!pOrcus->importGnumeric(aDocument, rMed))
1539 return false;
1541 else if (rFilterName == "csv")
1543 if (!pOrcus->importCSV(aDocument, rMed))
1544 return false;
1546 else if (rFilterName == "xlsx")
1548 if (!pOrcus->importXLSX(aDocument, rMed))
1549 return false;
1551 else if (rFilterName == "ods")
1553 if (!pOrcus->importODS(aDocument, rMed))
1554 return false;
1557 FinishedLoading(SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES);
1558 return true;
1561 return false;
1565 ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
1566 : mrDocShell( rDocShell)
1568 // DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
1570 ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
1571 if (pCharts)
1572 pCharts->UpdateDirtyCharts(); // Charts to be updated.
1573 mrDocShell.aDocument.StopTemporaryChartLock();
1574 if (mrDocShell.pAutoStyleList)
1575 mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
1576 if (mrDocShell.aDocument.HasExternalRefManager())
1578 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1579 if (pRefMgr && pRefMgr->hasExternalData())
1581 pRefMgr->setAllCacheTableReferencedStati( false);
1582 mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
1585 if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD)
1586 mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
1589 ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
1591 if (mrDocShell.aDocument.HasExternalRefManager())
1593 ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
1594 if (pRefMgr && pRefMgr->hasExternalData())
1596 // Prevent accidental data loss due to lack of knowledge.
1597 pRefMgr->setAllCacheTableReferencedStati( true);
1603 sal_Bool ScDocShell::Save()
1605 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1607 PrepareSaveGuard aPrepareGuard( *this);
1609 // wait cursor is handled with progress bar
1610 sal_Bool bRet = SfxObjectShell::Save();
1611 if( bRet )
1612 bRet = SaveXML( GetMedium(), NULL );
1613 return bRet;
1616 namespace {
1619 * Remove the file name from the full path, to keep only the directory path.
1621 void popFileName(OUString& rPath)
1623 if (!rPath.isEmpty())
1625 INetURLObject aURLObj(rPath);
1626 aURLObj.removeSegment();
1627 rPath = aURLObj.GetMainURL(INetURLObject::NO_DECODE);
1633 sal_Bool ScDocShell::SaveAs( SfxMedium& rMedium )
1635 OUString aCurPath; // empty for new document that hasn't been saved.
1636 const SfxMedium* pCurMedium = GetMedium();
1637 if (pCurMedium)
1639 aCurPath = pCurMedium->GetName();
1640 popFileName(aCurPath);
1643 if (!aCurPath.isEmpty())
1645 // current document has a path -> not a brand-new document.
1646 OUString aNewPath = rMedium.GetName();
1647 popFileName(aNewPath);
1648 OUString aRel = URIHelper::simpleNormalizedMakeRelative(aCurPath, aNewPath);
1649 if (!aRel.isEmpty())
1651 // Directory path will change before and after the save.
1652 aDocument.InvalidateStreamOnSave();
1656 ScTabViewShell* pViewShell = GetBestViewShell();
1657 bool bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_SHA1);
1658 if (bNeedsRehash)
1659 // legacy xls hash double-hashed by SHA1 is also supported.
1660 bNeedsRehash = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL, PASSHASH_SHA1);
1662 if (pViewShell && bNeedsRehash)
1664 if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_SHA1))
1665 // password re-type cancelled. Don't save the document.
1666 return false;
1670 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
1672 PrepareSaveGuard aPrepareGuard( *this);
1674 OUString aFltName = rMedium.GetFilter()->GetFilterName();
1675 bool bChartExport = aFltName.indexOf("chart8") != -1;
1677 // wait cursor is handled with progress bar
1678 sal_Bool bRet = false;
1679 if(!bChartExport)
1681 bRet = SfxObjectShell::SaveAs( rMedium );
1682 bRet = SaveXML( &rMedium, NULL );
1684 else
1686 bRet = SaveCurrentChart( rMedium );
1689 return bRet;
1693 sal_Bool ScDocShell::IsInformationLost()
1695 //!!! bei Gelegenheit ein korrekte eigene Behandlung einbauen
1697 return SfxObjectShell::IsInformationLost();
1700 namespace {
1702 // Xcl-like column width measured in characters of standard font.
1703 sal_Int32 lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth )
1705 double f = nWidth;
1706 f *= 1328.0 / 25.0;
1707 f += 90.0;
1708 f *= 1.0 / 23.0;
1709 f /= 256.0;
1711 return sal_Int32( f );
1715 void lcl_ScDocShell_GetFixedWidthString( OUString& rStr, const ScDocument& rDoc,
1716 SCTAB nTab, SCCOL nCol, sal_Bool bValue, SvxCellHorJustify eHorJust )
1718 OUString aString = rStr;
1719 sal_Int32 nLen = lcl_ScDocShell_GetColWidthInChars(
1720 rDoc.GetColWidth( nCol, nTab ) );
1721 //If the text won't fit in the column
1722 if ( nLen < aString.getLength() )
1724 OUStringBuffer aReplacement;
1725 if (bValue)
1726 aReplacement.append("###");
1727 else
1728 aReplacement.append(aString);
1729 //truncate to the number of characters that should fit, even in the
1730 //bValue case nLen might be < len ###
1731 aString = comphelper::string::truncateToLength(aReplacement, nLen).makeStringAndClear();
1733 if ( nLen > aString.getLength() )
1735 if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
1736 eHorJust = SVX_HOR_JUSTIFY_RIGHT;
1737 sal_Int32 nBlanks = nLen - aString.getLength();
1738 switch ( eHorJust )
1740 case SVX_HOR_JUSTIFY_RIGHT:
1742 OUStringBuffer aTmp;
1743 aTmp = comphelper::string::padToLength( aTmp, nBlanks, ' ' );
1744 aString = aTmp.append(aString).makeStringAndClear();
1746 break;
1747 case SVX_HOR_JUSTIFY_CENTER:
1749 sal_Int32 nLeftPad = nBlanks / 2;
1750 OUStringBuffer aTmp;
1751 comphelper::string::padToLength( aTmp, nLeftPad, ' ' );
1752 aTmp.append(aString);
1753 comphelper::string::padToLength( aTmp, nLen, ' ' );
1754 aString = aTmp.makeStringAndClear();
1756 break;
1757 default:
1759 OUStringBuffer aTmp(aString);
1760 comphelper::string::padToLength( aTmp, nLen, ' ' );
1761 aString = aTmp.makeStringAndClear();
1765 rStr = aString;
1769 void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
1770 const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
1772 OUString aString;
1773 lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, false,
1774 SVX_HOR_JUSTIFY_STANDARD );
1775 rStream.WriteUnicodeOrByteText( aString );
1778 template<typename StrT, typename SepCharT>
1779 sal_Int32 getTextSepPos(
1780 const StrT& rStr, const ScImportOptions& rAsciiOpt, const SepCharT& rTextSep, const SepCharT& rFieldSep, bool& rNeedQuotes)
1782 // #i116636# quotes are needed if text delimiter (quote), field delimiter,
1783 // or LF is in the cell text.
1784 sal_Int32 nPos = rStr.indexOf(rTextSep);
1785 rNeedQuotes = rAsciiOpt.bQuoteAllText || (nPos >= 0) ||
1786 (rStr.indexOf(rFieldSep) >= 0) ||
1787 (rStr.indexOf('\n') >= 0);
1788 return nPos;
1791 template<typename StrT, typename StrBufT>
1792 void escapeTextSep(sal_Int32 nPos, const StrT& rStrDelim, StrT& rStr)
1794 while (nPos >= 0)
1796 StrBufT aBuf(rStr);
1797 aBuf.insert(nPos, rStrDelim);
1798 rStr = aBuf.makeStringAndClear();
1799 nPos = rStr.indexOf(rStrDelim, nPos+1+rStrDelim.getLength());
1805 void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
1807 sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
1808 sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
1809 rtl_TextEncoding eCharSet = rAsciiOpt.eCharSet;
1810 bool bFixedWidth = rAsciiOpt.bFixedWidth;
1811 bool bSaveAsShown = rAsciiOpt.bSaveAsShown;
1812 bool bShowFormulas = rAsciiOpt.bSaveFormulas;
1814 rtl_TextEncoding eOldCharSet = rStream.GetStreamCharSet();
1815 rStream.SetStreamCharSet( eCharSet );
1816 sal_uInt16 nOldNumberFormatInt = rStream.GetNumberFormatInt();
1817 OString aStrDelimEncoded; // only used if not Unicode
1818 OUString aStrDelimDecoded; // only used if context encoding
1819 OString aDelimEncoded;
1820 OUString aDelimDecoded;
1821 bool bContextOrNotAsciiEncoding;
1822 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
1824 rStream.StartWritingUnicodeText();
1825 bContextOrNotAsciiEncoding = false;
1827 else
1829 aStrDelimEncoded = OString(&cStrDelim, 1, eCharSet);
1830 aDelimEncoded = OString(&cDelim, 1, eCharSet);
1831 rtl_TextEncodingInfo aInfo;
1832 aInfo.StructSize = sizeof(aInfo);
1833 if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
1835 bContextOrNotAsciiEncoding =
1836 (((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
1837 ((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
1838 if ( bContextOrNotAsciiEncoding )
1840 aStrDelimDecoded = OStringToOUString(aStrDelimEncoded, eCharSet);
1841 aDelimDecoded = OStringToOUString(aDelimEncoded, eCharSet);
1844 else
1845 bContextOrNotAsciiEncoding = false;
1848 SCCOL nStartCol = 0;
1849 SCROW nStartRow = 0;
1850 SCTAB nTab = GetSaveTab();
1851 SCCOL nEndCol;
1852 SCROW nEndRow;
1853 aDocument.GetCellArea( nTab, nEndCol, nEndRow );
1855 ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
1857 OUString aString;
1859 bool bTabProtect = aDocument.IsTabProtected( nTab );
1861 SCCOL nCol;
1862 SCROW nRow;
1863 SCCOL nNextCol = nStartCol;
1864 SCROW nNextRow = nStartRow;
1865 SCCOL nEmptyCol;
1866 SCROW nEmptyRow;
1867 SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
1869 ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
1870 nEndCol, nEndRow );
1871 ScRefCellValue* pCell;
1872 while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
1874 bool bProgress = false; // only upon line change
1875 if ( nNextRow < nRow )
1876 { // empty rows or/and empty columns up to end of row
1877 bProgress = true;
1878 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
1879 { // remaining columns of last row
1880 if ( bFixedWidth )
1881 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1882 aDocument, nTab, nEmptyCol );
1883 else if ( cDelim != 0 )
1884 rStream.WriteUniOrByteChar( cDelim );
1886 endlub( rStream );
1887 nNextRow++;
1888 for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
1889 { // completely empty rows
1890 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
1892 if ( bFixedWidth )
1893 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1894 aDocument, nTab, nEmptyCol );
1895 else if ( cDelim != 0 )
1896 rStream.WriteUniOrByteChar( cDelim );
1898 endlub( rStream );
1900 for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
1901 { // empty columns at beginning of row
1902 if ( bFixedWidth )
1903 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1904 aDocument, nTab, nEmptyCol );
1905 else if ( cDelim != 0 )
1906 rStream.WriteUniOrByteChar( cDelim );
1908 nNextRow = nRow;
1910 else if ( nNextCol < nCol )
1911 { // empty columns in same row
1912 for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
1913 { // columns in between
1914 if ( bFixedWidth )
1915 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
1916 aDocument, nTab, nEmptyCol );
1917 else if ( cDelim != 0 )
1918 rStream.WriteUniOrByteChar( cDelim );
1921 if ( nCol == nEndCol )
1923 bProgress = true;
1924 nNextCol = nStartCol;
1925 nNextRow = nRow + 1;
1927 else
1928 nNextCol = nCol + 1;
1930 CellType eType = pCell->meType;
1931 ScAddress aPos(nCol, nRow, nTab);
1932 if ( bTabProtect )
1934 const ScProtectionAttr* pProtAttr =
1935 (const ScProtectionAttr*) aDocument.GetAttr(
1936 nCol, nRow, nTab, ATTR_PROTECTION );
1937 if ( pProtAttr->GetHideCell() ||
1938 ( eType == CELLTYPE_FORMULA && bShowFormulas &&
1939 pProtAttr->GetHideFormula() ) )
1940 eType = CELLTYPE_NONE; // hide
1942 bool bString;
1943 switch ( eType )
1945 case CELLTYPE_NONE:
1946 aString = "";
1947 bString = false;
1948 break;
1949 case CELLTYPE_FORMULA :
1951 sal_uInt16 nErrCode;
1952 if ( bShowFormulas )
1954 pCell->mpFormula->GetFormula(aString);
1955 bString = true;
1957 else if ((nErrCode = pCell->mpFormula->GetErrCode()) != 0)
1959 aString = ScGlobal::GetErrorString( nErrCode );
1960 bString = true;
1962 else if (pCell->mpFormula->IsValue())
1964 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1965 if ( bFixedWidth || bSaveAsShown )
1967 Color* pDummy;
1968 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1969 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
1971 else
1973 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
1974 bString = false;
1977 else
1979 if ( bSaveAsShown )
1981 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1982 Color* pDummy;
1983 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1985 else
1986 aString = pCell->mpFormula->GetString().getString();
1987 bString = true;
1990 break;
1991 case CELLTYPE_STRING :
1992 if ( bSaveAsShown )
1994 sal_uInt32 nFormat = aDocument.GetNumberFormat(aPos);
1995 Color* pDummy;
1996 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
1998 else
1999 aString = pCell->mpString->getString();
2000 bString = true;
2001 break;
2002 case CELLTYPE_EDIT :
2004 const EditTextObject* pObj = pCell->mpEditText;
2005 EditEngine& rEngine = aDocument.GetEditEngine();
2006 rEngine.SetText( *pObj);
2007 aString = rEngine.GetText(); // including LF
2008 bString = true;
2010 break;
2011 case CELLTYPE_VALUE :
2013 sal_uInt32 nFormat;
2014 aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
2015 if ( bFixedWidth || bSaveAsShown )
2017 Color* pDummy;
2018 aString = ScCellFormat::GetString(aDocument, aPos, nFormat, &pDummy, rFormatter);
2019 bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
2021 else
2023 ScCellFormat::GetInputString(*pCell, nFormat, aString, rFormatter, &aDocument);
2024 bString = false;
2027 break;
2028 default:
2029 OSL_FAIL( "ScDocShell::AsciiSave: unknown CellType" );
2030 aString = "";
2031 bString = false;
2034 if ( bFixedWidth )
2036 SvxCellHorJustify eHorJust = (SvxCellHorJustify)
2037 ((const SvxHorJustifyItem*) aDocument.GetAttr( nCol, nRow,
2038 nTab, ATTR_HOR_JUSTIFY ))->GetValue();
2039 lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
2040 !bString, eHorJust );
2041 rStream.WriteUnicodeOrByteText( aString );
2043 else
2045 OUString aUniString = aString;//remove that later
2046 if (!bString && cStrDelim != 0 && !aUniString.isEmpty())
2048 sal_Unicode c = aUniString[0];
2049 bString = (c == cStrDelim || c == ' ' ||
2050 aUniString.endsWith(" ") ||
2051 aUniString.indexOf(cStrDelim) >= 0);
2052 if (!bString && cDelim != 0)
2053 bString = (aUniString.indexOf(cDelim) >= 0);
2055 if ( bString )
2057 if ( cStrDelim != 0 ) //@ BugId 55355
2059 if ( eCharSet == RTL_TEXTENCODING_UNICODE )
2061 bool bNeedQuotes = false;
2062 sal_Int32 nPos = getTextSepPos(
2063 aUniString, rAsciiOpt, cStrDelim, cDelim, bNeedQuotes);
2065 escapeTextSep<OUString, OUStringBuffer>(
2066 nPos, OUString(cStrDelim), aUniString);
2068 if ( bNeedQuotes )
2069 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2070 write_uInt16s_FromOUString(rStream, aUniString);
2071 if ( bNeedQuotes )
2072 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2074 else
2076 // This is nasty. The Unicode to byte encoding
2077 // may convert typographical quotation marks to ASCII
2078 // quotation marks, which may interfer with the delimiter,
2079 // so we have to escape delimiters after the string has
2080 // been encoded. Since this may happen also with UTF-8
2081 // encoded typographical quotation marks if such was
2082 // specified as a delimiter we have to check for the full
2083 // encoded delimiter string, not just one character.
2084 // Now for RTL_TEXTENCODING_ISO_2022_... and similar brain
2085 // dead encodings where one code point (and especially a
2086 // low ASCII value) may represent different characters, we
2087 // have to convert forth and back and forth again. Same for
2088 // UTF-7 since it is a context sensitive encoding too.
2090 if ( bContextOrNotAsciiEncoding )
2092 // to byte encoding
2093 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2094 // back to Unicode
2095 OUString aStrDec = OStringToOUString(aStrEnc, eCharSet);
2097 // search on re-decoded string
2098 bool bNeedQuotes = false;
2099 sal_Int32 nPos = getTextSepPos(
2100 aStrDec, rAsciiOpt, aStrDelimDecoded, aDelimDecoded, bNeedQuotes);
2102 escapeTextSep<OUString, OUStringBuffer>(
2103 nPos, aStrDelimDecoded, aStrDec);
2105 // write byte re-encoded
2106 if ( bNeedQuotes )
2107 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2108 rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
2109 if ( bNeedQuotes )
2110 rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
2112 else
2114 OString aStrEnc = OUStringToOString(aUniString, eCharSet);
2116 // search on encoded string
2117 bool bNeedQuotes = false;
2118 sal_Int32 nPos = getTextSepPos(
2119 aStrEnc, rAsciiOpt, aStrDelimEncoded, aDelimEncoded, bNeedQuotes);
2121 escapeTextSep<OString, OStringBuffer>(
2122 nPos, aStrDelimEncoded, aStrEnc);
2124 // write byte encoded
2125 if ( bNeedQuotes )
2126 rStream.Write(
2127 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2128 rStream.Write(aStrEnc.getStr(), aStrEnc.getLength());
2129 if ( bNeedQuotes )
2130 rStream.Write(
2131 aStrDelimEncoded.getStr(), aStrDelimEncoded.getLength());
2135 else
2136 rStream.WriteUnicodeOrByteText( aUniString );
2138 else
2139 rStream.WriteUnicodeOrByteText( aUniString );
2142 if( nCol < nEndCol )
2144 if(cDelim!=0) //@ BugId 55355
2145 rStream.WriteUniOrByteChar( cDelim );
2147 else
2148 endlub( rStream );
2150 if ( bProgress )
2151 aProgress.SetStateOnPercent( nRow );
2154 // write out empty if requested
2155 if ( nNextRow <= nEndRow )
2157 for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
2158 { // remaining empty columns of last row
2159 if ( bFixedWidth )
2160 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2161 aDocument, nTab, nEmptyCol );
2162 else if ( cDelim != 0 )
2163 rStream.WriteUniOrByteChar( cDelim );
2165 endlub( rStream );
2166 nNextRow++;
2168 for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
2169 { // entire empty rows
2170 for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
2172 if ( bFixedWidth )
2173 lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
2174 aDocument, nTab, nEmptyCol );
2175 else if ( cDelim != 0 )
2176 rStream.WriteUniOrByteChar( cDelim );
2178 endlub( rStream );
2181 rStream.SetStreamCharSet( eOldCharSet );
2182 rStream.SetNumberFormatInt( nOldNumberFormatInt );
2185 sal_Bool ScDocShell::ConvertTo( SfxMedium &rMed )
2187 ScRefreshTimerProtector aProt( aDocument.GetRefreshTimerControlAddress() );
2189 // #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
2190 // it's already in ExecuteSave (as for Save and SaveAs)
2192 if (pAutoStyleList)
2193 pAutoStyleList->ExecuteAllNow(); // Vorlagen-Timeouts jetzt ausfuehren
2194 if (GetCreateMode()== SFX_CREATE_MODE_STANDARD)
2195 SfxObjectShell::SetVisArea( Rectangle() ); // normal bearbeitet -> keine VisArea
2197 OSL_ENSURE( rMed.GetFilter(), "Filter == 0" );
2199 sal_Bool bRet = false;
2200 OUString aFltName = rMed.GetFilter()->GetFilterName();
2202 if (aFltName.equalsAscii(pFilterXML))
2204 //TODO/LATER: this shouldn't happen!
2205 OSL_FAIL("XML filter in ConvertFrom?!");
2206 bRet = SaveXML( &rMed, NULL );
2208 else if (aFltName.equalsAscii(pFilterExcel5) || aFltName.equalsAscii(pFilterExcel95) ||
2209 aFltName.equalsAscii(pFilterExcel97) || aFltName.equalsAscii(pFilterEx5Temp) ||
2210 aFltName.equalsAscii(pFilterEx95Temp) || aFltName.equalsAscii(pFilterEx97Temp))
2212 WaitObject aWait( GetActiveDialogParent() );
2214 bool bDoSave = true;
2215 if( ScTabViewShell* pViewShell = GetBestViewShell() )
2217 ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
2218 if( !pExtDocOpt )
2219 aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
2220 pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
2222 /* #i104990# If the imported document contains a medium
2223 password, determine if we can save it, otherwise ask the users
2224 whether they want to save without it. */
2225 if( (rMed.GetFilter()->GetFilterFlags() & SFX_FILTER_ENCRYPTION) == 0 )
2227 SfxItemSet* pItemSet = rMed.GetItemSet();
2228 const SfxPoolItem* pItem = 0;
2229 if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, sal_True, &pItem ) == SFX_ITEM_SET )
2231 bDoSave = ScWarnPassword::WarningOnPassword( rMed );
2232 // #i42858# remove password from medium (warn only one time)
2233 if( bDoSave )
2234 pItemSet->ClearItem( SID_PASSWORD );
2238 if( bDoSave )
2240 bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
2241 bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
2245 if( bDoSave )
2247 ExportFormatExcel eFormat = ExpBiff5;
2248 if( aFltName.equalsAscii( pFilterExcel97 ) || aFltName.equalsAscii( pFilterEx97Temp ) )
2249 eFormat = ExpBiff8;
2250 FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
2252 if( eError && !GetError() )
2253 SetError( eError, OUString( OSL_LOG_PREFIX ) );
2255 // don't return false for warnings
2256 bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
2258 else
2260 // export aborted, i.e. "Save without password" warning
2261 SetError( ERRCODE_ABORT, OUString( OSL_LOG_PREFIX ) );
2264 else if (aFltName.equalsAscii(pFilterAscii))
2266 SvStream* pStream = rMed.GetOutStream();
2267 if (pStream)
2269 OUString sItStr;
2270 SfxItemSet* pSet = rMed.GetItemSet();
2271 const SfxPoolItem* pItem;
2272 if ( pSet && SFX_ITEM_SET ==
2273 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
2275 sItStr = ((const SfxStringItem*)pItem)->GetValue();
2278 if ( sItStr.isEmpty() )
2280 // default for ascii export (from API without options):
2281 // ISO8859-1/MS_1252 encoding, comma, double quotes
2283 ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
2284 sItStr = aDefOptions.BuildString();
2287 WaitObject aWait( GetActiveDialogParent() );
2288 ScImportOptions aOptions( sItStr );
2289 AsciiSave( *pStream, aOptions );
2290 bRet = sal_True;
2292 if (aDocument.GetTableCount() > 1)
2293 if (!rMed.GetError())
2294 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2297 else if (aFltName.equalsAscii(pFilterDBase))
2299 OUString sCharSet;
2300 SfxItemSet* pSet = rMed.GetItemSet();
2301 const SfxPoolItem* pItem;
2302 if ( pSet && SFX_ITEM_SET ==
2303 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
2305 sCharSet = ((const SfxStringItem*)pItem)->GetValue();
2308 if (sCharSet.isEmpty())
2310 // default for dBase export (from API without options):
2311 // IBM_850 encoding
2313 sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
2316 WaitObject aWait( GetActiveDialogParent() );
2317 // HACK damit Sba geoffnetes TempFile ueberschreiben kann
2318 rMed.CloseOutStream();
2319 bool bHasMemo = false;
2321 sal_uLong eError = DBaseExport(
2322 rMed.GetPhysicalName(), ScGlobal::GetCharsetValue(sCharSet), bHasMemo);
2324 if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
2326 eError = eERR_OK;
2329 INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE );
2330 if ( bHasMemo )
2331 aTmpFile.setExtension(OUString("dbt"));
2332 if ( eError != eERR_OK )
2334 if (!GetError())
2335 SetError(eError, OUString( OSL_LOG_PREFIX ));
2336 if ( bHasMemo && IsDocument( aTmpFile ) )
2337 KillFile( aTmpFile );
2339 else
2341 bRet = sal_True;
2342 if ( bHasMemo )
2344 SfxStringItem* pNameItem =
2345 (SfxStringItem*) rMed.GetItemSet()->GetItem( SID_FILE_NAME );
2346 INetURLObject aDbtFile( pNameItem->GetValue(), INET_PROT_FILE );
2347 aDbtFile.setExtension(OUString("dbt"));
2348 if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
2349 bRet = false;
2350 if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
2351 bRet = false;
2352 if ( !bRet )
2354 KillFile( aTmpFile );
2355 if ( !GetError() )
2356 SetError( SCERR_EXPORT_DATA, OUString( OSL_LOG_PREFIX ) );
2361 else if (aFltName.equalsAscii(pFilterDif))
2363 SvStream* pStream = rMed.GetOutStream();
2364 if (pStream)
2366 OUString sItStr;
2367 SfxItemSet* pSet = rMed.GetItemSet();
2368 const SfxPoolItem* pItem;
2369 if ( pSet && SFX_ITEM_SET ==
2370 pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
2372 sItStr = ((const SfxStringItem*)pItem)->GetValue();
2375 if (sItStr.isEmpty())
2377 // default for DIF export (from API without options):
2378 // ISO8859-1/MS_1252 encoding
2380 sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
2383 WaitObject aWait( GetActiveDialogParent() );
2384 ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
2385 ScGlobal::GetCharsetValue(sItStr) );
2386 bRet = sal_True;
2388 if (aDocument.GetTableCount() > 1)
2389 if (!rMed.GetError())
2390 rMed.SetError(SCWARN_EXPORT_ASCII, OUString( OSL_LOG_PREFIX ));
2393 else if (aFltName.equalsAscii(pFilterSylk))
2395 SvStream* pStream = rMed.GetOutStream();
2396 if ( pStream )
2398 WaitObject aWait( GetActiveDialogParent() );
2400 SCCOL nEndCol;
2401 SCROW nEndRow;
2402 aDocument.GetCellArea( 0, nEndCol, nEndRow );
2403 ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
2405 ScImportExport aImExport( &aDocument, aRange );
2406 aImExport.SetFormulas( sal_True );
2407 bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_SYLK );
2410 else if (aFltName.equalsAscii(pFilterHtml))
2412 SvStream* pStream = rMed.GetOutStream();
2413 if ( pStream )
2415 WaitObject aWait( GetActiveDialogParent() );
2416 ScImportExport aImExport( &aDocument );
2417 aImExport.SetStreamPath( rMed.GetName() );
2418 bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_HTML );
2419 if ( bRet && !aImExport.GetNonConvertibleChars().isEmpty() )
2420 SetError( *new StringErrorInfo(
2421 SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
2422 aImExport.GetNonConvertibleChars(),
2423 ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO ), OUString( OSL_LOG_PREFIX ) );
2426 else
2428 if (GetError())
2429 SetError(SCERR_IMPORT_NI, OUString( OSL_LOG_PREFIX ) );
2431 return bRet;
2435 sal_Bool ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
2437 return SfxObjectShell::SaveCompleted( xStor );
2441 sal_Bool ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
2443 sal_Bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
2445 // SC_HINT_DOC_SAVED fuer Wechsel ReadOnly -> Read/Write
2446 Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
2447 return bRet;
2451 sal_Bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId )
2453 // #i112634# ask VBA event handlers whether to save or print the document
2455 using namespace ::com::sun::star::script::vba;
2457 sal_Int32 nVbaEventId = VBAEventId::NO_EVENT;
2458 uno::Sequence< uno::Any > aArgs;
2459 switch( nSlotId )
2461 case SID_SAVEDOC:
2462 case SID_SAVEASDOC:
2463 nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE;
2464 aArgs.realloc( 1 );
2465 aArgs[ 0 ] <<= (nSlotId == SID_SAVEASDOC);
2466 break;
2467 case SID_PRINTDOC:
2468 case SID_PRINTDOCDIRECT:
2469 nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT;
2470 break;
2473 sal_Bool bSlotExecutable = sal_True;
2474 if( nVbaEventId != VBAEventId::NO_EVENT ) try
2476 uno::Reference< XVBAEventProcessor > xEventProcessor( aDocument.GetVbaEventProcessor(), uno::UNO_QUERY_THROW );
2477 xEventProcessor->processVbaEvent( nVbaEventId, aArgs );
2479 catch( util::VetoException& )
2481 bSlotExecutable = false;
2483 catch( uno::Exception& )
2486 return bSlotExecutable;
2490 sal_uInt16 ScDocShell::PrepareClose( sal_Bool bUI, sal_Bool bForBrowsing )
2492 if(SC_MOD()->GetCurRefDlgId()>0)
2494 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
2495 if( pFrame )
2497 SfxViewShell* p = pFrame->GetViewShell();
2498 ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
2499 if(pViewSh!=NULL)
2501 Window *pWin=pViewSh->GetWindow();
2502 if(pWin!=NULL) pWin->GrabFocus();
2506 return false;
2508 if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
2510 ErrorMessage(STR_CLOSE_ERROR_LINK);
2511 return false;
2514 DoEnterHandler();
2516 // start 'Workbook_BeforeClose' VBA event handler for possible veto
2517 if( !IsInPrepareClose() )
2521 uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( aDocument.GetVbaEventProcessor(), uno::UNO_SET_THROW );
2522 uno::Sequence< uno::Any > aArgs;
2523 xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs );
2525 catch( util::VetoException& )
2527 // if event processor throws VetoException, macro has vetoed close
2528 return false;
2530 catch( uno::Exception& )
2534 // end handler code
2536 sal_uInt16 nRet = SfxObjectShell::PrepareClose( bUI, bForBrowsing );
2537 if (nRet == sal_True) // sal_True = schliessen
2538 aDocument.EnableIdle(false); // nicht mehr drin rumpfuschen !!!
2540 return nRet;
2543 void ScDocShell::PrepareReload()
2545 SfxObjectShell::PrepareReload(); // tut nichts?
2547 // Das Disconnect von DDE-Links kann Reschedule ausloesen.
2548 // Wenn die DDE-Links erst im Dokument-dtor geloescht werden, kann beim Reload
2549 // aus diesem Reschedule das DDE-Link-Update fuer das neue Dokument ausgeloest
2550 // werden. Dabei verklemmt sicht dann irgendwas.
2551 // -> Beim Reload die DDE-Links des alten Dokuments vorher disconnecten
2553 aDocument.DisconnectDdeLinks();
2557 OUString ScDocShell::GetOwnFilterName()
2559 return OUString(pFilterSc50);
2562 OUString ScDocShell::GetHtmlFilterName()
2564 return OUString(pFilterHtml);
2567 OUString ScDocShell::GetWebQueryFilterName()
2569 return OUString(pFilterHtmlWebQ);
2572 OUString ScDocShell::GetAsciiFilterName()
2574 return OUString(pFilterAscii);
2577 OUString ScDocShell::GetLotusFilterName()
2579 return OUString(pFilterLotus);
2582 OUString ScDocShell::GetDBaseFilterName()
2584 return OUString(pFilterDBase);
2587 OUString ScDocShell::GetDifFilterName()
2589 return OUString(pFilterDif);
2592 sal_Bool ScDocShell::HasAutomaticTableName( const OUString& rFilter )
2594 // sal_True for those filters that keep the default table name
2595 // (which is language specific)
2597 return rFilter.equalsAscii( pFilterAscii )
2598 || rFilter.equalsAscii( pFilterLotus )
2599 || rFilter.equalsAscii( pFilterExcel4 )
2600 || rFilter.equalsAscii( pFilterEx4Temp )
2601 || rFilter.equalsAscii( pFilterDBase )
2602 || rFilter.equalsAscii( pFilterDif )
2603 || rFilter.equalsAscii( pFilterSylk )
2604 || rFilter.equalsAscii( pFilterHtml )
2605 || rFilter.equalsAscii( pFilterRtf );
2608 #if ! ENABLE_TELEPATHY
2609 ScDocFunc *ScDocShell::CreateDocFunc()
2611 return new ScDocFuncDirect( *this );
2613 #else
2614 ScCollaboration* ScDocShell::GetCollaboration()
2616 return mpCollaboration;
2618 #endif
2620 ScDocShell::ScDocShell( const ScDocShell& rShell ) :
2621 SvRefBase(),
2622 SotObject(),
2623 SfxObjectShell( rShell.GetCreateMode() ),
2624 SfxListener(),
2625 aDocument ( SCDOCMODE_DOCUMENT, this ),
2626 aDdeTextFmt(OUString("TEXT")),
2627 nPrtToScreenFactor( 1.0 ),
2628 pImpl ( new DocShell_Impl ),
2629 bHeaderOn ( true ),
2630 bFooterOn ( true ),
2631 bIsEmpty ( true ),
2632 bIsInUndo ( false ),
2633 bDocumentModifiedPending( false ),
2634 bUpdateEnabled ( true ),
2635 nDocumentLock ( 0 ),
2636 nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2637 pOldAutoDBRange ( NULL ),
2638 pDocHelper ( NULL ),
2639 pAutoStyleList ( NULL ),
2640 pPaintLockData ( NULL ),
2641 pSolverSaveData ( NULL ),
2642 pSheetSaveData ( NULL ),
2643 pModificator ( NULL )
2644 #if ENABLE_TELEPATHY
2645 , mpCollaboration( new ScCollaboration( this ) )
2646 #endif
2648 SetPool( &SC_MOD()->GetPool() );
2650 bIsInplace = rShell.bIsInplace;
2652 pDocFunc = CreateDocFunc();
2654 // SetBaseModel needs exception handling
2655 ScModelObj::CreateAndSet( this );
2657 StartListening(*this);
2658 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2659 if (pStlPool)
2660 StartListening(*pStlPool);
2662 GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
2663 SetHelpId( HID_SCSHELL_DOCSH );
2665 // InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
2668 //------------------------------------------------------------------
2670 ScDocShell::ScDocShell( const sal_uInt64 i_nSfxCreationFlags ) :
2671 SfxObjectShell( i_nSfxCreationFlags ),
2672 aDocument ( SCDOCMODE_DOCUMENT, this ),
2673 aDdeTextFmt(OUString("TEXT")),
2674 nPrtToScreenFactor( 1.0 ),
2675 pImpl ( new DocShell_Impl ),
2676 bHeaderOn ( true ),
2677 bFooterOn ( true ),
2678 bIsEmpty ( true ),
2679 bIsInUndo ( false ),
2680 bDocumentModifiedPending( false ),
2681 bUpdateEnabled ( true ),
2682 nDocumentLock ( 0 ),
2683 nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG),
2684 pOldAutoDBRange ( NULL ),
2685 pDocHelper ( NULL ),
2686 pAutoStyleList ( NULL ),
2687 pPaintLockData ( NULL ),
2688 pSolverSaveData ( NULL ),
2689 pSheetSaveData ( NULL ),
2690 pModificator ( NULL )
2691 #if ENABLE_TELEPATHY
2692 , mpCollaboration( new ScCollaboration( this ) )
2693 #endif
2695 SetPool( &SC_MOD()->GetPool() );
2697 bIsInplace = (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
2698 // wird zurueckgesetzt, wenn nicht inplace
2700 pDocFunc = CreateDocFunc();
2702 // SetBaseModel needs exception handling
2703 ScModelObj::CreateAndSet( this );
2705 StartListening(*this);
2706 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2707 if (pStlPool)
2708 StartListening(*pStlPool);
2709 SetHelpId( HID_SCSHELL_DOCSH );
2711 aDocument.GetDBCollection()->SetRefreshHandler(
2712 LINK( this, ScDocShell, RefreshDBDataHdl ) );
2714 // InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
2717 //------------------------------------------------------------------
2719 ScDocShell::~ScDocShell()
2721 ResetDrawObjectShell(); // falls der Drawing-Layer noch versucht, darauf zuzugreifen
2723 SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
2724 if (pStlPool)
2725 EndListening(*pStlPool);
2726 EndListening(*this);
2728 delete pAutoStyleList;
2730 SfxApplication *pSfxApp = SFX_APP();
2731 if ( pSfxApp->GetDdeService() ) // DDE vor Dokument loeschen
2732 pSfxApp->RemoveDdeTopic( this );
2734 delete pDocFunc;
2735 delete aDocument.mpUndoManager;
2736 aDocument.mpUndoManager = 0;
2737 delete pImpl;
2739 delete pPaintLockData;
2741 delete pSolverSaveData;
2742 delete pSheetSaveData;
2743 delete pOldAutoDBRange;
2745 if (pModificator)
2747 OSL_FAIL("The Modificator should not exist");
2748 delete pModificator;
2750 #if ENABLE_TELEPATHY
2751 delete mpCollaboration;
2752 #endif
2755 //------------------------------------------------------------------
2757 ::svl::IUndoManager* ScDocShell::GetUndoManager()
2759 return aDocument.GetUndoManager();
2762 void ScDocShell::SetModified( sal_Bool bModified )
2764 if ( SfxObjectShell::IsEnableSetModified() )
2766 SfxObjectShell::SetModified( bModified );
2767 Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
2772 void ScDocShell::SetDocumentModified( sal_Bool bIsModified /* = sal_True */ )
2774 // BroadcastUno muss auch mit pPaintLockData sofort passieren
2775 //! auch bei SetDrawModified, wenn Drawing angebunden ist
2776 //! dann eigener Hint???
2778 if ( pPaintLockData && bIsModified )
2780 // #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results
2781 // of RecalcModeAlways formulas (like OFFSET) after modifying cells
2782 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2783 aDocument.InvalidateTableArea(); // #i105279# needed here
2784 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2786 pPaintLockData->SetModified(); // spaeter...
2787 return;
2790 SetDrawModified( bIsModified );
2792 if ( bIsModified )
2794 if ( aDocument.IsAutoCalcShellDisabled() )
2795 SetDocumentModifiedPending( sal_True );
2796 else
2798 SetDocumentModifiedPending( false );
2799 aDocument.InvalidateStyleSheetUsage();
2800 aDocument.InvalidateTableArea();
2801 aDocument.InvalidateLastTableOpParams();
2802 aDocument.Broadcast(ScHint(SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS));
2803 if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
2804 aDocument.CalcFormulaTree( sal_True );
2805 PostDataChanged();
2807 // Detective AutoUpdate:
2808 // Update if formulas were modified (DetectiveDirty) or the list contains
2809 // "Trace Error" entries (Trace Error can look completely different
2810 // after changes to non-formula cells).
2812 ScDetOpList* pList = aDocument.GetDetOpList();
2813 if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
2814 pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
2816 GetDocFunc().DetectiveRefresh(sal_True); // sal_True = caused by automatic update
2818 aDocument.SetDetectiveDirty(false); // always reset, also if not refreshed
2821 // notify UNO objects after BCA_BRDCST_ALWAYS etc.
2822 aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
2826 // SetDrawModified - ohne Formel-Update
2827 // (Drawing muss auch beim normalen SetDocumentModified upgedated werden,
2828 // z.B. bei Tabelle loeschen etc.)
2830 void ScDocShell::SetDrawModified( sal_Bool bIsModified /* = sal_True */ )
2832 sal_Bool bUpdate = ( bIsModified != IsModified() );
2834 SetModified( bIsModified );
2836 SfxBindings* pBindings = GetViewBindings();
2837 if (bUpdate)
2839 if (pBindings)
2841 pBindings->Invalidate( SID_SAVEDOC );
2842 pBindings->Invalidate( SID_DOC_MODIFIED );
2846 if (bIsModified)
2848 if (pBindings)
2850 // #i105960# Undo etc used to be volatile.
2851 // They always have to be invalidated, including drawing layer or row height changes
2852 // (but not while pPaintLockData is set).
2853 pBindings->Invalidate( SID_UNDO );
2854 pBindings->Invalidate( SID_REDO );
2855 pBindings->Invalidate( SID_REPEAT );
2858 if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
2860 aDocument.UpdateChartListenerCollection();
2861 SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
2863 SC_MOD()->AnythingChanged();
2867 void ScDocShell::SetInUndo(bool bSet)
2869 bIsInUndo = bSet;
2873 void ScDocShell::GetDocStat( ScDocStat& rDocStat )
2875 SfxPrinter* pPrinter = GetPrinter();
2877 aDocument.GetDocStat( rDocStat );
2878 rDocStat.nPageCount = 0;
2880 if ( pPrinter )
2881 for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
2882 rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount +
2883 (sal_uInt16) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
2887 SfxDocumentInfoDialog* ScDocShell::CreateDocumentInfoDialog(
2888 Window *pParent, const SfxItemSet &rSet )
2890 SfxDocumentInfoDialog* pDlg = new SfxDocumentInfoDialog( pParent, rSet );
2891 ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
2893 //nur mit Statistik, wenn dieses Doc auch angezeigt wird, nicht
2894 //aus dem Doc-Manager
2896 if( pDocSh == this )
2898 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
2899 OSL_ENSURE(pFact, "ScAbstractFactory create fail!");
2900 ::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
2901 OSL_ENSURE(ScDocStatPageCreate, "Tabpage create fail!");
2902 pDlg->AddFontTabPage();
2903 pDlg->AddTabPage( 42,
2904 ScGlobal::GetRscString( STR_DOC_STAT ),
2905 ScDocStatPageCreate,
2906 NULL);
2908 return pDlg;
2911 Window* ScDocShell::GetActiveDialogParent()
2913 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2914 if ( pViewSh )
2915 return pViewSh->GetDialogParent();
2916 else
2917 return Application::GetDefDialogParent();
2920 void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
2922 delete pSolverSaveData;
2923 pSolverSaveData = new ScOptSolverSave( rData );
2926 ScSheetSaveData* ScDocShell::GetSheetSaveData()
2928 if (!pSheetSaveData)
2929 pSheetSaveData = new ScSheetSaveData;
2931 return pSheetSaveData;
2934 namespace {
2936 void removeKeysIfExists(Reference<ui::XAcceleratorConfiguration>& xScAccel, const vector<const awt::KeyEvent*>& rKeys)
2938 vector<const awt::KeyEvent*>::const_iterator itr = rKeys.begin(), itrEnd = rKeys.end();
2939 for (; itr != itrEnd; ++itr)
2941 const awt::KeyEvent* p = *itr;
2942 if (!p)
2943 continue;
2947 xScAccel->removeKeyEvent(*p);
2949 catch (const container::NoSuchElementException&) {}
2955 void ScDocShell::ResetKeyBindings( ScOptionsUtil::KeyBindingType eType )
2957 using namespace ::com::sun::star::ui;
2959 Reference<uno::XComponentContext> xContext = ::comphelper::getProcessComponentContext();
2960 if (!xContext.is())
2961 return;
2963 Reference<XModuleUIConfigurationManagerSupplier> xModuleCfgSupplier(
2964 ModuleUIConfigurationManagerSupplier::create(xContext) );
2966 // Grab the Calc configuration.
2967 Reference<XUIConfigurationManager> xConfigMgr =
2968 xModuleCfgSupplier->getUIConfigurationManager(
2969 OUString("com.sun.star.sheet.SpreadsheetDocument"));
2971 if (!xConfigMgr.is())
2972 return;
2974 // shortcut manager
2975 Reference<XAcceleratorConfiguration> xScAccel = xConfigMgr->getShortCutManager();
2977 if (!xScAccel.is())
2978 return;
2980 vector<const awt::KeyEvent*> aKeys;
2981 aKeys.reserve(4);
2983 // Backsapce key
2984 awt::KeyEvent aBackspace;
2985 aBackspace.KeyCode = awt::Key::BACKSPACE;
2986 aBackspace.Modifiers = 0;
2987 aKeys.push_back(&aBackspace);
2989 // Delete key
2990 awt::KeyEvent aDelete;
2991 aDelete.KeyCode = awt::Key::DELETE;
2992 aDelete.Modifiers = 0;
2993 aKeys.push_back(&aDelete);
2995 // Ctrl-D
2996 awt::KeyEvent aCtrlD;
2997 aCtrlD.KeyCode = awt::Key::D;
2998 aCtrlD.Modifiers = awt::KeyModifier::MOD1;
2999 aKeys.push_back(&aCtrlD);
3001 // Alt-Down
3002 awt::KeyEvent aAltDown;
3003 aAltDown.KeyCode = awt::Key::DOWN;
3004 aAltDown.Modifiers = awt::KeyModifier::MOD2;
3005 aKeys.push_back(&aAltDown);
3007 // Remove all involved keys first, because swapping commands don't work
3008 // well without doing this.
3009 removeKeysIfExists(xScAccel, aKeys);
3010 xScAccel->store();
3012 switch (eType)
3014 case ScOptionsUtil::KEY_DEFAULT:
3015 xScAccel->setKeyEvent(aDelete, OUString(".uno:ClearContents"));
3016 xScAccel->setKeyEvent(aBackspace, OUString(".uno:Delete"));
3017 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:FillDown"));
3018 xScAccel->setKeyEvent(aAltDown, OUString(".uno:DataSelect"));
3019 break;
3020 case ScOptionsUtil::KEY_OOO_LEGACY:
3021 xScAccel->setKeyEvent(aDelete, OUString(".uno:Delete"));
3022 xScAccel->setKeyEvent(aBackspace, OUString(".uno:ClearContents"));
3023 xScAccel->setKeyEvent(aCtrlD, OUString(".uno:DataSelect"));
3024 break;
3025 default:
3029 xScAccel->store();
3032 void ScDocShell::UseSheetSaveEntries()
3034 if (pSheetSaveData)
3036 pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
3038 bool bHasEntries = false;
3039 SCTAB nTabCount = aDocument.GetTableCount();
3040 SCTAB nTab;
3041 for (nTab = 0; nTab < nTabCount; ++nTab)
3042 if (pSheetSaveData->HasStreamPos(nTab))
3043 bHasEntries = true;
3045 if (!bHasEntries)
3047 // if no positions were set (for example, export to other format),
3048 // reset all "valid" flags
3050 for (nTab = 0; nTab < nTabCount; ++nTab)
3051 if (aDocument.IsStreamValid(nTab))
3052 aDocument.SetStreamValid(nTab, false);
3057 // --- ScDocShellModificator ------------------------------------------
3059 ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
3061 rDocShell( rDS ),
3062 mpProtector(new ScRefreshTimerProtector(rDS.GetDocument()->GetRefreshTimerControlAddress()))
3064 ScDocument* pDoc = rDocShell.GetDocument();
3065 bAutoCalcShellDisabled = pDoc->IsAutoCalcShellDisabled();
3066 bIdleEnabled = pDoc->IsIdleEnabled();
3067 pDoc->SetAutoCalcShellDisabled( true );
3068 pDoc->EnableIdle(false);
3072 ScDocShellModificator::~ScDocShellModificator()
3074 ScDocument* pDoc = rDocShell.GetDocument();
3075 pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3076 if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
3077 rDocShell.SetDocumentModified(); // last one shuts off the lights
3078 pDoc->EnableIdle(bIdleEnabled);
3082 void ScDocShellModificator::SetDocumentModified()
3084 ScDocument* pDoc = rDocShell.GetDocument();
3085 pDoc->CellContentModified();
3086 if ( !pDoc->IsImportingXML() )
3088 // AutoCalcShellDisabled temporaer restaurieren
3089 bool bDisabled = pDoc->IsAutoCalcShellDisabled();
3090 pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
3091 rDocShell.SetDocumentModified();
3092 pDoc->SetAutoCalcShellDisabled( bDisabled );
3094 else
3096 // uno broadcast is necessary for api to work
3097 // -> must also be done during xml import
3098 pDoc->BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
3102 bool ScDocShell::IsChangeRecording() const
3104 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3105 return pChangeTrack != NULL;
3109 bool ScDocShell::HasChangeRecordProtection() const
3111 bool bRes = false;
3112 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3113 if (pChangeTrack)
3114 bRes = pChangeTrack->IsProtected();
3115 return bRes;
3119 void ScDocShell::SetChangeRecording( bool bActivate )
3121 bool bOldChangeRecording = IsChangeRecording();
3123 if (bActivate)
3125 aDocument.StartChangeTracking();
3126 ScChangeViewSettings aChangeViewSet;
3127 aChangeViewSet.SetShowChanges(sal_True);
3128 aDocument.SetChangeViewSettings(aChangeViewSet);
3130 else
3132 aDocument.EndChangeTracking();
3133 PostPaintGridAll();
3136 if (bOldChangeRecording != IsChangeRecording())
3138 UpdateAcceptChangesDialog();
3139 // Slots invalidieren
3140 SfxBindings* pBindings = GetViewBindings();
3141 if (pBindings)
3142 pBindings->InvalidateAll(false);
3147 bool ScDocShell::SetProtectionPassword( const OUString &rNewPassword )
3149 bool bRes = false;
3150 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3151 if (pChangeTrack)
3153 bool bProtected = pChangeTrack->IsProtected();
3155 if (!rNewPassword.isEmpty())
3157 // when password protection is applied change tracking must always be active
3158 SetChangeRecording( true );
3160 ::com::sun::star::uno::Sequence< sal_Int8 > aProtectionHash;
3161 SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword );
3162 pChangeTrack->SetProtection( aProtectionHash );
3164 else
3166 pChangeTrack->SetProtection( ::com::sun::star::uno::Sequence< sal_Int8 >() );
3168 bRes = true;
3170 if ( bProtected != pChangeTrack->IsProtected() )
3172 UpdateAcceptChangesDialog();
3173 SetDocumentModified();
3177 return bRes;
3181 bool ScDocShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > &rPasswordHash )
3183 bool bRes = false;
3184 ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
3185 if (pChangeTrack && pChangeTrack->IsProtected())
3187 rPasswordHash = pChangeTrack->GetProtection();
3188 bRes = true;
3190 return bRes;
3193 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */