Bug Summary

File:home/maarten/src/libreoffice/core/include/rtl/ref.hxx
Warning:line 192, column 9
Use of memory after it is freed

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-unknown-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name docsh.cxx -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mframe-pointer=all -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib64/clang/11.0.0 -isystem /usr/include/libxml2 -D BOOST_ERROR_CODE_HEADER_ONLY -D BOOST_SYSTEM_NO_DEPRECATED -D CPPU_ENV=gcc3 -D LINUX -D OSL_DEBUG_LEVEL=1 -D SAL_LOG_INFO -D SAL_LOG_WARN -D UNIX -D UNX -D X86_64 -D _PTHREADS -D _REENTRANT -D SC_DLLIMPLEMENTATION -D SC_INFO_OSVERSION="LINUX" -D SYSTEM_LIBXML -D EXCEPTIONS_ON -D LIBO_INTERNAL_ONLY -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/liborcus/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/mdds/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/i18n -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/icu/source/common -I /home/maarten/src/libreoffice/core/external/clew/source/include -I /home/maarten/src/libreoffice/core/external/boost/include -I /home/maarten/src/libreoffice/core/workdir/UnpackedTarball/boost -I /home/maarten/src/libreoffice/core/sc/source/core/inc -I /home/maarten/src/libreoffice/core/sc/source/filter/inc -I /home/maarten/src/libreoffice/core/sc/source/ui/inc -I /home/maarten/src/libreoffice/core/sc/inc -I /home/maarten/src/libreoffice/core/workdir/SdiTarget/sc/sdi -I /home/maarten/src/libreoffice/core/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include -I /usr/lib/jvm/java-11-openjdk-11.0.9.10-0.0.ea.fc33.x86_64/include/linux -I /home/maarten/src/libreoffice/core/config_host -I /home/maarten/src/libreoffice/core/workdir/CustomTarget/officecfg/registry -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/udkapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/offapi/normal -I /home/maarten/src/libreoffice/core/workdir/UnoApiHeadersTarget/oovbaapi/normal -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10 -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/x86_64-redhat-linux -internal-isystem /usr/bin/../lib/gcc/x86_64-redhat-linux/10/../../../../include/c++/10/backward -internal-isystem /usr/local/include -internal-isystem /usr/lib64/clang/11.0.0/include -internal-externc-isystem /include -internal-externc-isystem /usr/include -O0 -Wno-missing-braces -std=c++17 -fdeprecated-macro -fdebug-compilation-dir /home/maarten/src/libreoffice/core -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -fcxx-exceptions -fexceptions -debug-info-kind=constructor -analyzer-output=html -faddrsig -o /home/maarten/tmp/wis/scan-build-libreoffice/output/report/2020-10-07-141433-9725-1 -x c++ /home/maarten/src/libreoffice/core/sc/source/ui/docshell/docsh.cxx

/home/maarten/src/libreoffice/core/sc/source/ui/docshell/docsh.cxx

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

/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_VCL_PTR_HXX
21#define INCLUDED_VCL_PTR_HXX
22
23#include <sal/config.h>
24
25#include <rtl/ref.hxx>
26
27#include <utility>
28#include <type_traits>
29
30#ifdef DBG_UTIL
31#ifndef _WIN32
32#include <vcl/vclmain.hxx>
33#endif
34#endif
35
36class VclReferenceBase;
37
38namespace vcl::detail {
39
40template<typename>
41constexpr bool isIncompleteOrDerivedFromVclReferenceBase(...) { return true; }
42
43template<typename T> constexpr bool isIncompleteOrDerivedFromVclReferenceBase(
44 int (*)[sizeof(T)])
45{ return std::is_base_of<VclReferenceBase, T>::value; }
46
47} // namespace vcl::detail
48
49/**
50 * A thin wrapper around rtl::Reference to implement the acquire and dispose semantics we want for references to vcl::Window subclasses.
51 *
52 * For more details on the design please see vcl/README.lifecycle
53 *
54 * @param reference_type must be a subclass of vcl::Window
55 */
56template <class reference_type>
57class VclPtr
58{
59 static_assert(
60 vcl::detail::isIncompleteOrDerivedFromVclReferenceBase<reference_type>(
61 nullptr),
62 "template argument type must be derived from VclReferenceBase");
63
64 ::rtl::Reference<reference_type> m_rInnerRef;
65
66public:
67 /** Constructor...
68 */
69 VclPtr()
70 : m_rInnerRef()
71 {}
72
73 /** Constructor...
74 */
75 VclPtr (reference_type * pBody)
76 : m_rInnerRef(pBody)
77 {}
78
79 /** Constructor... that doesn't take a ref.
80 */
81 VclPtr (reference_type * pBody, __sal_NoAcquire)
82 : m_rInnerRef(pBody, SAL_NO_ACQUIRE)
83 {}
84
85 /** Up-casting conversion constructor: Copies interface reference.
86
87 Does not work for up-casts to ambiguous bases. For the special case of
88 up-casting to Reference< XInterface >, see the corresponding conversion
89 operator.
90
91 @param rRef another reference
92 */
93 template< class derived_type >
94 VclPtr(
95 const VclPtr< derived_type > & rRef,
96 typename std::enable_if<
97 std::is_base_of<reference_type, derived_type>::value, int>::type
98 = 0 )
99 : m_rInnerRef( static_cast<reference_type*>(rRef) )
100 {
101 }
102
103#if defined(DBG_UTIL) && !defined(_WIN32)
104 virtual ~VclPtr()
105 {
106 assert(m_rInnerRef.get() == nullptr || vclmain::isAlive())(static_cast <bool> (m_rInnerRef.get() == nullptr || vclmain
::isAlive()) ? void (0) : __assert_fail ("m_rInnerRef.get() == nullptr || vclmain::isAlive()"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 106, __extension__ __PRETTY_FUNCTION__))
;
107 // We can be one of the intermediate counts, but if we are the last
108 // VclPtr keeping this object alive, then something forgot to call dispose().
109 assert((!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1)(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
110 && "someone forgot to call dispose()")(static_cast <bool> ((!m_rInnerRef.get() || m_rInnerRef
->isDisposed() || m_rInnerRef->getRefCount() > 1) &&
"someone forgot to call dispose()") ? void (0) : __assert_fail
("(!m_rInnerRef.get() || m_rInnerRef->isDisposed() || m_rInnerRef->getRefCount() > 1) && \"someone forgot to call dispose()\""
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 110, __extension__ __PRETTY_FUNCTION__))
;
111 }
112 VclPtr(VclPtr const &) = default;
113 VclPtr(VclPtr &&) = default;
114 VclPtr & operator =(VclPtr const &) = default;
115 VclPtr & operator =(VclPtr &&) = default;
116#endif
117
118 /**
119 * A construction helper for VclPtr. Since VclPtr types are created
120 * with a reference-count of one - to help fit into the existing
121 * code-flow; this helps us to construct them easily.
122 *
123 * For more details on the design please see vcl/README.lifecycle
124 *
125 * @tparam reference_type must be a subclass of vcl::Window
126 */
127 template<typename... Arg> [[nodiscard]] static VclPtr< reference_type > Create(Arg &&... arg)
128 {
129 return VclPtr< reference_type >( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE );
130 }
131
132 /** Probably most common used: handle->someBodyOp().
133 */
134 reference_type * operator->() const
135 {
136 return m_rInnerRef.get();
137 }
138
139 /** Get the body. Can be used instead of operator->().
140 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
141 are the same.
142 */
143 reference_type * get() const
144 {
145 return m_rInnerRef.get();
146 }
147
148 void set(reference_type *pBody)
149 {
150 m_rInnerRef.set(pBody);
151 }
152
153 void reset(reference_type *pBody)
154 {
155 m_rInnerRef.set(pBody);
156 }
157
158 /** Up-casting copy assignment operator.
159
160 Does not work for up-casts to ambiguous bases.
161
162 @param rRef another reference
163 */
164 template<typename derived_type>
165 typename std::enable_if<
166 std::is_base_of<reference_type, derived_type>::value,
167 VclPtr &>::type
168 operator =(VclPtr<derived_type> const & rRef)
169 {
170 m_rInnerRef.set(rRef.get());
171 return *this;
172 }
173
174 VclPtr & operator =(reference_type * pBody)
175 {
176 m_rInnerRef.set(pBody);
177 return *this;
178 }
179
180 operator reference_type * () const
181 {
182 return m_rInnerRef.get();
183 }
184
185 explicit operator bool () const
186 {
187 return m_rInnerRef.get() != nullptr;
188 }
189
190 void clear()
191 {
192 m_rInnerRef.clear();
193 }
194
195 void reset()
196 {
197 m_rInnerRef.clear();
198 }
199
200 void disposeAndClear()
201 {
202 // hold it alive for the lifetime of this method
203 ::rtl::Reference<reference_type> aTmp(m_rInnerRef);
204 m_rInnerRef.clear(); // we should use some 'swap' method ideally ;-)
20
Calling 'Reference::clear'
27
Returning; memory was released
205 if (aTmp.get()) {
28
Calling 'Reference::get'
206 aTmp->disposeOnce();
207 }
208 }
209
210 /** Needed to place VclPtr's into STL collection.
211 */
212 bool operator< (const VclPtr<reference_type> & handle) const
213 {
214 return (m_rInnerRef < handle.m_rInnerRef);
215 }
216}; // class VclPtr
217
218template<typename T1, typename T2>
219inline bool operator ==(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
220 return p1.get() == p2.get();
221}
222
223template<typename T> inline bool operator ==(VclPtr<T> const & p1, T const * p2)
224{
225 return p1.get() == p2;
226}
227
228template<typename T> inline bool operator ==(VclPtr<T> const & p1, T * p2) {
229 return p1.get() == p2;
230}
231
232template<typename T> inline bool operator ==(T const * p1, VclPtr<T> const & p2)
233{
234 return p1 == p2.get();
235}
236
237template<typename T> inline bool operator ==(T * p1, VclPtr<T> const & p2) {
238 return p1 == p2.get();
239}
240
241template<typename T1, typename T2>
242inline bool operator !=(VclPtr<T1> const & p1, VclPtr<T2> const & p2) {
243 return !(p1 == p2);
244}
245
246template<typename T> inline bool operator !=(VclPtr<T> const & p1, T const * p2)
247{
248 return !(p1 == p2);
249}
250
251template<typename T> inline bool operator !=(VclPtr<T> const & p1, T * p2) {
252 return !(p1 == p2);
253}
254
255template<typename T> inline bool operator !=(T const * p1, VclPtr<T> const & p2)
256{
257 return !(p1 == p2);
258}
259
260template<typename T> inline bool operator !=(T * p1, VclPtr<T> const & p2) {
261 return !(p1 == p2);
262}
263
264/**
265 * A construction helper for a temporary VclPtr. Since VclPtr types
266 * are created with a reference-count of one - to help fit into
267 * the existing code-flow; this helps us to construct them easily.
268 * see also VclPtr::Create and ScopedVclPtr
269 *
270 * For more details on the design please see vcl/README.lifecycle
271 *
272 * @param reference_type must be a subclass of vcl::Window
273 */
274template <class reference_type>
275class SAL_WARN_UNUSED__attribute__((warn_unused)) VclPtrInstance final : public VclPtr<reference_type>
276{
277public:
278 template<typename... Arg> VclPtrInstance(Arg &&... arg)
279 : VclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
280 {
281 }
282
283 /**
284 * Override and disallow this, to prevent people accidentally calling it and actually
285 * getting VclPtr::Create and getting a naked VclPtr<> instance
286 */
287 template<typename... Arg> static VclPtrInstance< reference_type > Create(Arg &&... ) = delete;
288};
289
290template <class reference_type>
291class ScopedVclPtr : public VclPtr<reference_type>
292{
293public:
294 /** Constructor...
295 */
296 ScopedVclPtr()
297 : VclPtr<reference_type>()
298 {}
299
300 /** Constructor
301 */
302 ScopedVclPtr (reference_type * pBody)
303 : VclPtr<reference_type>(pBody)
304 {}
305
306 /** Copy constructor...
307 */
308 ScopedVclPtr (const VclPtr<reference_type> & handle)
309 : VclPtr<reference_type>(handle)
310 {}
311
312 /**
313 Assignment that releases the last reference.
314 */
315 void disposeAndReset(reference_type *pBody)
316 {
317 if (pBody != this->get()) {
318 VclPtr<reference_type>::disposeAndClear();
319 VclPtr<reference_type>::set(pBody);
320 }
321 }
322
323 /**
324 Assignment that releases the last reference.
325 */
326 ScopedVclPtr<reference_type>& operator = (reference_type * pBody)
327 {
328 disposeAndReset(pBody);
329 return *this;
330 }
331
332 /** Up-casting conversion constructor: Copies interface reference.
333
334 Does not work for up-casts to ambiguous bases. For the special case of
335 up-casting to Reference< XInterface >, see the corresponding conversion
336 operator.
337
338 @param rRef another reference
339 */
340 template< class derived_type >
341 ScopedVclPtr(
342 const VclPtr< derived_type > & rRef,
343 typename std::enable_if<
344 std::is_base_of<reference_type, derived_type>::value, int>::type
345 = 0 )
346 : VclPtr<reference_type>( rRef )
347 {
348 }
349
350 /** Up-casting assignment operator.
351
352 Does not work for up-casts to ambiguous bases.
353
354 @param rRef another VclPtr
355 */
356 template<typename derived_type>
357 typename std::enable_if<
358 std::is_base_of<reference_type, derived_type>::value,
359 ScopedVclPtr &>::type
360 operator =(VclPtr<derived_type> const & rRef)
361 {
362 disposeAndReset(rRef.get());
363 return *this;
364 }
365
366 /**
367 * Override and disallow this, to prevent people accidentally calling it and actually
368 * getting VclPtr::Create and getting a naked VclPtr<> instance
369 */
370 template<typename... Arg> static ScopedVclPtr< reference_type > Create(Arg &&... ) = delete;
371
372 ~ScopedVclPtr()
373 {
374 VclPtr<reference_type>::disposeAndClear();
19
Calling 'VclPtr::disposeAndClear'
375 assert(VclPtr<reference_type>::get() == nullptr)(static_cast <bool> (VclPtr<reference_type>::get(
) == nullptr) ? void (0) : __assert_fail ("VclPtr<reference_type>::get() == nullptr"
, "/home/maarten/src/libreoffice/core/include/vcl/vclptr.hxx"
, 375, __extension__ __PRETTY_FUNCTION__))
; // make sure there are no lingering references
376 }
377
378private:
379 // Most likely we don't want this default copy-constructor.
380 ScopedVclPtr (const ScopedVclPtr<reference_type> &) = delete;
381 // And certainly we don't want a default assignment operator.
382 ScopedVclPtr<reference_type>& operator = (const ScopedVclPtr<reference_type> &) = delete;
383 // And disallow reset as that doesn't call disposeAndClear on the original reference
384 void reset() = delete;
385 void reset(reference_type *pBody) = delete;
386
387protected:
388 ScopedVclPtr (reference_type * pBody, __sal_NoAcquire)
389 : VclPtr<reference_type>(pBody, SAL_NO_ACQUIRE)
390 {}
391};
392
393/**
394 * A construction helper for ScopedVclPtr. Since VclPtr types are created
395 * with a reference-count of one - to help fit into the existing
396 * code-flow; this helps us to construct them easily.
397 *
398 * For more details on the design please see vcl/README.lifecycle
399 *
400 * @param reference_type must be a subclass of vcl::Window
401 */
402#if defined _MSC_VER
403#pragma warning(push)
404#pragma warning(disable: 4521) // " multiple copy constructors specified"
405#endif
406template <class reference_type>
407class SAL_WARN_UNUSED__attribute__((warn_unused)) ScopedVclPtrInstance final : public ScopedVclPtr<reference_type>
408{
409public:
410 template<typename... Arg> ScopedVclPtrInstance(Arg &&... arg)
411 : ScopedVclPtr<reference_type>( new reference_type(std::forward<Arg>(arg)...), SAL_NO_ACQUIRE )
12
Memory is allocated
412 {
413 }
414
415 /**
416 * Override and disallow this, to prevent people accidentally calling it and actually
417 * getting VclPtr::Create and getting a naked VclPtr<> instance
418 */
419 template<typename... Arg> static ScopedVclPtrInstance< reference_type > Create(Arg &&...) = delete;
420
421private:
422 // Prevent the above perfect forwarding ctor from hijacking (accidental)
423 // attempts at ScopedVclPtrInstance copy construction (where the hijacking
424 // would typically lead to somewhat obscure error messages); both non-const
425 // and const variants are needed here, as the ScopedVclPtr base class has a
426 // const--variant copy ctor, so the implicitly declared copy ctor for
427 // ScopedVclPtrInstance would also be the const variant, so non-const copy
428 // construction attempts would be hijacked by the perfect forwarding ctor;
429 // but if we only declared a non-const variant here, the const variant would
430 // no longer be implicitly declared (as there would already be an explicitly
431 // declared copy ctor), so const copy construction attempts would then be
432 // hijacked by the perfect forwarding ctor:
433 ScopedVclPtrInstance(ScopedVclPtrInstance &) = delete;
434 ScopedVclPtrInstance(ScopedVclPtrInstance const &) = delete;
435};
436#if defined _MSC_VER
437#pragma warning(pop)
438#endif
439
440#endif // INCLUDED_VCL_PTR_HXX
441
442/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/rtl/ref.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#ifndef INCLUDED_RTL_REF_HXX
21#define INCLUDED_RTL_REF_HXX
22
23#include "sal/config.h"
24
25#include <cassert>
26#include <cstddef>
27#include <functional>
28#ifdef LIBO_INTERNAL_ONLY1
29#include <type_traits>
30#endif
31
32#include "sal/types.h"
33
34namespace rtl
35{
36
37/** Template reference class for reference type.
38*/
39template <class reference_type>
40class Reference
41{
42 /** The <b>reference_type</b> body pointer.
43 */
44 reference_type * m_pBody;
45
46
47public:
48 /** Constructor...
49 */
50 Reference()
51 : m_pBody (NULL__null)
52 {}
53
54
55 /** Constructor...
56 */
57 Reference (reference_type * pBody, __sal_NoAcquire)
58 : m_pBody (pBody)
59 {
60 }
61
62 /** Constructor...
63 */
64 Reference (reference_type * pBody)
65 : m_pBody (pBody)
66 {
67 if (m_pBody)
68 m_pBody->acquire();
69 }
70
71 /** Copy constructor...
72 */
73 Reference (const Reference<reference_type> & handle)
74 : m_pBody (handle.m_pBody)
75 {
76 if (m_pBody)
77 m_pBody->acquire();
78 }
79
80#ifdef LIBO_INTERNAL_ONLY1
81 /** Move constructor...
82 */
83 Reference (Reference<reference_type> && handle) noexcept
84 : m_pBody (handle.m_pBody)
85 {
86 handle.m_pBody = nullptr;
87 }
88#endif
89
90#if defined LIBO_INTERNAL_ONLY1
91 /** Up-casting conversion constructor: Copies interface reference.
92
93 Does not work for up-casts to ambiguous bases.
94
95 @param rRef another reference
96 */
97 template< class derived_type >
98 inline Reference(
99 const Reference< derived_type > & rRef,
100 std::enable_if_t<std::is_base_of_v<reference_type, derived_type>, int> = 0 )
101 : m_pBody (rRef.get())
102 {
103 if (m_pBody)
104 m_pBody->acquire();
105 }
106#endif
107
108 /** Destructor...
109 */
110 ~Reference() COVERITY_NOEXCEPT_FALSE
111 {
112 if (m_pBody)
113 m_pBody->release();
114 }
115
116 /** Set...
117 Similar to assignment.
118 */
119 Reference<reference_type> &
120 SAL_CALL set (reference_type * pBody)
121 {
122 if (pBody)
123 pBody->acquire();
124 reference_type * const pOld = m_pBody;
125 m_pBody = pBody;
126 if (pOld)
127 pOld->release();
128 return *this;
129 }
130
131 /** Assignment.
132 Unbinds this instance from its body (if bound) and
133 bind it to the body represented by the handle.
134 */
135 Reference<reference_type> &
136 SAL_CALL operator= (const Reference<reference_type> & handle)
137 {
138 return set( handle.m_pBody );
139 }
140
141#ifdef LIBO_INTERNAL_ONLY1
142 /** Assignment.
143 * Unbinds this instance from its body (if bound),
144 * bind it to the body represented by the handle, and
145 * set the body represented by the handle to nullptr.
146 */
147 Reference<reference_type> &
148 operator= (Reference<reference_type> && handle)
149 {
150 // self-movement guts ourself
151 if (m_pBody)
152 m_pBody->release();
153 m_pBody = handle.m_pBody;
154 handle.m_pBody = nullptr;
155 return *this;
156 }
157#endif
158
159 /** Assignment...
160 */
161 Reference<reference_type> &
162 SAL_CALL operator= (reference_type * pBody)
163 {
164 return set( pBody );
165 }
166
167 /** Unbind the body from this handle.
168 Note that for a handle representing a large body,
169 "handle.clear().set(new body());" _might_
170 perform a little bit better than "handle.set(new body());",
171 since in the second case two large objects exist in memory
172 (the old body and the new body).
173 */
174 Reference<reference_type> & SAL_CALL clear()
175 {
176 if (m_pBody
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
20.1
Field 'm_pBody' is non-null
)
21
Taking true branch
177 {
178 reference_type * const pOld = m_pBody;
179 m_pBody = NULL__null;
180 pOld->release();
22
Calling 'VclReferenceBase::release'
26
Returning; memory was released
181 }
182 return *this;
183 }
184
185
186 /** Get the body. Can be used instead of operator->().
187 I.e. handle->someBodyOp() and handle.get()->someBodyOp()
188 are the same.
189 */
190 reference_type * SAL_CALL get() const
191 {
192 return m_pBody;
29
Use of memory after it is freed
193 }
194
195
196 /** Probably most common used: handle->someBodyOp().
197 */
198 reference_type * SAL_CALL operator->() const
199 {
200 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 200, __extension__ __PRETTY_FUNCTION__))
;
201 return m_pBody;
202 }
203
204
205 /** Allows (*handle).someBodyOp().
206 */
207 reference_type & SAL_CALL operator*() const
208 {
209 assert(m_pBody != NULL)(static_cast <bool> (m_pBody != __null) ? void (0) : __assert_fail
("m_pBody != NULL", "/home/maarten/src/libreoffice/core/include/rtl/ref.hxx"
, 209, __extension__ __PRETTY_FUNCTION__))
;
210 return *m_pBody;
211 }
212
213
214 /** Returns True if the handle does point to a valid body.
215 */
216 bool SAL_CALL is() const
217 {
218 return (m_pBody != NULL__null);
219 }
220
221#if defined LIBO_INTERNAL_ONLY1
222 /** Returns True if the handle does point to a valid body.
223 */
224 explicit operator bool() const
225 {
226 return is();
227 }
228#endif
229
230 /** Returns True if this points to pBody.
231 */
232 bool SAL_CALL operator== (const reference_type * pBody) const
233 {
234 return (m_pBody == pBody);
235 }
236
237
238 /** Returns True if handle points to the same body.
239 */
240 bool
241 SAL_CALL operator== (const Reference<reference_type> & handle) const
242 {
243 return (m_pBody == handle.m_pBody);
244 }
245
246
247 /** Needed to place References into STL collection.
248 */
249 bool
250 SAL_CALL operator!= (const Reference<reference_type> & handle) const
251 {
252 return (m_pBody != handle.m_pBody);
253 }
254
255
256 /** Needed to place References into STL collection.
257 */
258 bool
259 SAL_CALL operator< (const Reference<reference_type> & handle) const
260 {
261 return (m_pBody < handle.m_pBody);
262 }
263
264
265 /** Needed to place References into STL collection.
266 */
267 bool
268 SAL_CALL operator> (const Reference<reference_type> & handle) const
269 {
270 return (m_pBody > handle.m_pBody);
271 }
272};
273
274} // namespace rtl
275
276#if defined LIBO_INTERNAL_ONLY1
277namespace std
278{
279
280/// @cond INTERNAL
281/**
282 Make rtl::Reference hashable by default for use in STL containers.
283
284 @since LibreOffice 6.3
285*/
286template<typename T>
287struct hash<::rtl::Reference<T>>
288{
289 std::size_t operator()(::rtl::Reference<T> const & s) const
290 { return std::size_t(s.get()); }
291};
292/// @endcond
293
294}
295
296#endif
297
298#endif /* ! INCLUDED_RTL_REF_HXX */
299
300/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

/home/maarten/src/libreoffice/core/include/vcl/vclreferencebase.hxx

1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19#ifndef INCLUDED_VCL_Reference_HXX
20#define INCLUDED_VCL_Reference_HXX
21
22#include <vcl/dllapi.h>
23#include <osl/interlck.h>
24
25class VCL_DLLPUBLIC__attribute__ ((visibility("default"))) VclReferenceBase
26{
27 mutable oslInterlockedCount mnRefCnt;
28
29 template<typename T> friend class VclPtr;
30
31public:
32 void acquire() const
33 {
34 osl_atomic_increment(&mnRefCnt)__sync_add_and_fetch((&mnRefCnt), 1);
35 }
36
37 void release() const
38 {
39 if (osl_atomic_decrement(&mnRefCnt)__sync_sub_and_fetch((&mnRefCnt), 1) == 0)
23
Assuming the condition is true
24
Taking true branch
40 delete this;
25
Memory is released
41 }
42#ifdef DBG_UTIL
43#ifndef _WIN32
44 sal_Int32 getRefCount() const { return mnRefCnt; }
45#endif
46#endif
47
48
49private:
50 VclReferenceBase(const VclReferenceBase&) = delete;
51 VclReferenceBase& operator=(const VclReferenceBase&) = delete;
52
53 bool mbDisposed : 1;
54
55protected:
56 VclReferenceBase();
57protected:
58 virtual ~VclReferenceBase();
59
60protected:
61 virtual void dispose();
62
63public:
64 void disposeOnce();
65 bool isDisposed() const { return mbDisposed; }
66
67};
68#endif