blob: 93c7d1bc7ae3aa3a1c6fbe69e7cacbc69cd7785f [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sc.hxx"
// System - Includes -----------------------------------------------------
#include "scitems.hxx"
#include <editeng/eeitem.hxx>
#include <editeng/svxenum.hxx>
#include <svx/algitem.hxx>
#include <sot/clsids.hxx>
#include <unotools/securityoptions.hxx>
#include <tools/stream.hxx>
#include <tools/string.hxx>
#include <tools/urlobj.hxx>
#include <vcl/msgbox.hxx>
#include <vcl/virdev.hxx>
#include <vcl/waitobj.hxx>
#include <svtools/ctrltool.hxx>
#include <svtools/sfxecode.hxx>
#include <svl/zforlist.hxx>
#include <svl/PasswordHelper.hxx>
#include <sfx2/app.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dinfdlg.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/docfilt.hxx>
#include <sfx2/fcontnr.hxx>
#include <sfx2/evntconf.hxx>
#include <sfx2/sfx.hrc>
#include <sfx2/objface.hxx>
#include <svl/srchitem.hxx>
#include <unotools/fltrcfg.hxx>
#include <svl/documentlockfile.hxx>
#include <svl/sharecontrolfile.hxx>
#include <unotools/charclass.hxx>
#include <vcl/virdev.hxx>
#include "chgtrack.hxx"
#include "chgviset.hxx"
#include <sfx2/request.hxx>
#include <com/sun/star/container/XContentEnumerationAccess.hpp>
#include <com/sun/star/document/UpdateDocMode.hpp>
#include <com/sun/star/script/vba/VBAEventId.hpp>
#include <com/sun/star/script/vba/XVBAEventProcessor.hpp>
#include <com/sun/star/sheet/XSpreadsheetView.hpp>
#include <com/sun/star/task/XJob.hpp>
#include <com/sun/star/embed/EmbedStates.hpp>
#include <basic/sbstar.hxx>
#include <basic/basmgr.hxx>
#include "scabstdlg.hxx" //CHINA001
#include <sot/formats.hxx>
#define SOT_FORMATSTR_ID_STARCALC_30 SOT_FORMATSTR_ID_STARCALC
// INCLUDE ---------------------------------------------------------------
#include "cell.hxx"
#include "global.hxx"
#include "filter.hxx"
#include "scmod.hxx"
#include "tabvwsh.hxx"
#include "docfunc.hxx"
#include "imoptdlg.hxx"
#include "impex.hxx"
#include "scresid.hxx"
#include "sc.hrc"
#include "globstr.hrc"
#include "scerrors.hxx"
#include "brdcst.hxx"
#include "stlpool.hxx"
#include "autostyl.hxx"
#include "attrib.hxx"
#include "asciiopt.hxx"
#include "waitoff.hxx"
#include "docpool.hxx" // LoadCompleted
#include "progress.hxx"
#include "pntlock.hxx"
#include "collect.hxx"
#include "docuno.hxx"
#include "appoptio.hxx"
#include "detdata.hxx"
#include "printfun.hxx"
#include "dociter.hxx"
#include "cellform.hxx"
#include "chartlis.hxx"
#include "hints.hxx"
#include "xmlwrap.hxx"
#include "drwlayer.hxx"
#include "refreshtimer.hxx"
#include "dbcolect.hxx"
#include "scextopt.hxx"
#include "compiler.hxx"
#include "cfgids.hxx"
#include "warnpassword.hxx"
#include "optsolver.hxx"
#include "sheetdata.hxx"
#include "tabprotection.hxx"
#include "dpobject.hxx"
#include "docsh.hxx"
#include "docshimp.hxx"
#include <sfx2/viewfrm.hxx>
#include <rtl/logfile.hxx>
#include <comphelper/processfactory.hxx>
#include "uiitems.hxx"
#include "cellsuno.hxx"
using namespace com::sun::star;
using ::rtl::OUString;
using ::rtl::OUStringBuffer;
// STATIC DATA -----------------------------------------------------------
// Stream-Namen im Storage
const sal_Char __FAR_DATA ScDocShell::pStarCalcDoc[] = STRING_SCSTREAM; // "StarCalcDocument"
const sal_Char __FAR_DATA ScDocShell::pStyleName[] = "SfxStyleSheets";
// Filter-Namen (wie in sclib.cxx)
static const sal_Char __FAR_DATA pFilterSc50[] = "StarCalc 5.0";
//static const sal_Char __FAR_DATA pFilterSc50Temp[] = "StarCalc 5.0 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterSc40[] = "StarCalc 4.0";
//static const sal_Char __FAR_DATA pFilterSc40Temp[] = "StarCalc 4.0 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterSc30[] = "StarCalc 3.0";
//static const sal_Char __FAR_DATA pFilterSc30Temp[] = "StarCalc 3.0 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterSc10[] = "StarCalc 1.0";
static const sal_Char __FAR_DATA pFilterXML[] = "StarOffice XML (Calc)";
static const sal_Char __FAR_DATA pFilterAscii[] = "Text - txt - csv (StarCalc)";
static const sal_Char __FAR_DATA pFilterLotus[] = "Lotus";
static const sal_Char __FAR_DATA pFilterQPro6[] = "Quattro Pro 6.0";
static const sal_Char __FAR_DATA pFilterExcel4[] = "MS Excel 4.0";
static const sal_Char __FAR_DATA pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterExcel5[] = "MS Excel 5.0/95";
static const sal_Char __FAR_DATA pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterExcel95[] = "MS Excel 95";
static const sal_Char __FAR_DATA pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterExcel97[] = "MS Excel 97";
static const sal_Char __FAR_DATA pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template";
static const sal_Char __FAR_DATA pFilterEx07Xml[] = "MS Excel 2007 XML";
static const sal_Char __FAR_DATA pFilterDBase[] = "dBase";
static const sal_Char __FAR_DATA pFilterDif[] = "DIF";
static const sal_Char __FAR_DATA pFilterSylk[] = "SYLK";
static const sal_Char __FAR_DATA pFilterHtml[] = "HTML (StarCalc)";
static const sal_Char __FAR_DATA pFilterHtmlWebQ[] = "calc_HTML_WebQuery";
static const sal_Char __FAR_DATA pFilterRtf[] = "Rich Text Format (StarCalc)";
//----------------------------------------------------------------------
#define ScDocShell
#include "scslots.hxx"
namespace
{
template< bool bByName >
inline sal_uInt8 GetMediumFlag( const String & rName )
{
sal_uInt8 bResult = E_MEDIUM_FLAG_NONE;
#define SFX2_FILTER_ENTRY( entry ) { #entry, (sizeof #entry)/sizeof((#entry)[0]) - 1 },
static const struct
{
const char * mpFilterTypeName;
unsigned mnFilterTypeLen;
} szMSFilterTypes [] =
{
SFX2_FILTER_ENTRY(calc_MS_Excel_40)
SFX2_FILTER_ENTRY(calc_MS_Excel_40_VorlageTemplate)
SFX2_FILTER_ENTRY(calc_MS_Excel_5095)
SFX2_FILTER_ENTRY(calc_MS_Excel_5095_VorlageTemplate)
SFX2_FILTER_ENTRY(calc_MS_Excel_95)
SFX2_FILTER_ENTRY(calc_MS_Excel_95_VorlageTemplate)
SFX2_FILTER_ENTRY(calc_MS_Excel_97)
SFX2_FILTER_ENTRY(calc_MS_Excel_97_VorlageTemplate)
SFX2_FILTER_ENTRY(calc_MS_Excel_2003_XML)
SFX2_FILTER_ENTRY(MS Excel 2007 XML)
SFX2_FILTER_ENTRY(MS Excel 2007 XML Template)
SFX2_FILTER_ENTRY(MS Excel 2007 Binary)
};
static const struct
{
const char * mpFilterName;
size_t mnFilterNameLen;
} szMSFilterNames [] =
{
{ pFilterExcel4, strlen( pFilterExcel4 ) },
{ pFilterEx4Temp, strlen( pFilterEx4Temp ) },
{ pFilterExcel95, strlen( pFilterExcel95 ) },
{ pFilterEx95Temp, strlen( pFilterEx95Temp ) },
{ pFilterExcel5, strlen( pFilterExcel5 ) },
{ pFilterEx5Temp, strlen( pFilterEx5Temp ) },
{ pFilterExcel97, strlen( pFilterExcel97 ) },
{ pFilterEx97Temp, strlen( pFilterEx97Temp ) },
SFX2_FILTER_ENTRY(Microsoft Excel 2003 XML)
{ pFilterEx07Xml, strlen( pFilterEx07Xml ) },
SFX2_FILTER_ENTRY(Microsoft Excel 2007 XML Template)
SFX2_FILTER_ENTRY(Microsoft Excel 2007 Binary)
};
enum{
e_calc_MS_Excel_40,
e_calc_MS_Excel_40_VorlageTemplate,
e_calc_MS_Excel_5095,
e_calc_MS_Excel_5095_VorlageTemplate,
e_calc_MS_Excel_95,
Se_calc_MS_Excel_95_VorlageTemplate,
e_calc_MS_Excel_97,
e_calc_MS_Excel_97_VorlageTemplate,
e_calc_MS_Excel_2003_XML,
e_MS_Excel_2007_XML,
e_MS_Excel_2007_XML_Template,
e_MS_Excel_2007_Binary
};
#undef SFX2_FILTER_ENTRY
if( bByName )
{
for( unsigned i = 0; i < (sizeof szMSFilterNames)/sizeof(szMSFilterNames[0] ); i++ )
if( rName.Len() == szMSFilterNames[i].mnFilterNameLen
&& std::equal( szMSFilterNames[i].mpFilterName, szMSFilterNames[i].mpFilterName + szMSFilterNames[i].mnFilterNameLen, rName.GetBuffer() ) )
bResult |= ( E_MEDIUM_FLAG_EXCEL | ( ( i == e_MS_Excel_2007_XML ) * E_MEDIUM_FLAG_MSXML ) );
}
else
{
for( unsigned i = 0; i < (sizeof szMSFilterTypes)/sizeof(szMSFilterTypes[0] ); i++ )
if( rName.Len() == szMSFilterTypes[i].mnFilterTypeLen
&& std::equal( szMSFilterTypes[i].mpFilterTypeName, szMSFilterTypes[i].mpFilterTypeName + szMSFilterTypes[i].mnFilterTypeLen, rName.GetBuffer() ) )
bResult |= ( E_MEDIUM_FLAG_EXCEL | ( ( i == e_MS_Excel_2007_XML ) * E_MEDIUM_FLAG_MSXML ) );
}
return bResult;
}
inline sal_uInt8 GetMediumFlag( const SfxMedium * pMedium )
{
if( const SfxFilter * pFilter = pMedium ? pMedium->GetFilter() : NULL )
return GetMediumFlag<false>( pFilter->GetTypeName() );
return E_MEDIUM_FLAG_NONE;
}
}
SFX_IMPL_INTERFACE(ScDocShell,SfxObjectShell, ScResId(SCSTR_DOCSHELL))
{
SFX_CHILDWINDOW_REGISTRATION( SID_HYPERLINK_INSERT );
}
// GlobalName der aktuellen Version:
SFX_IMPL_OBJECTFACTORY( ScDocShell, SvGlobalName(SO3_SC_CLASSID), SFXOBJECTSHELL_STD_NORMAL, "scalc" )
TYPEINIT1( ScDocShell, SfxObjectShell ); // SfxInPlaceObject: kein Type-Info ?
//------------------------------------------------------------------
void __EXPORT ScDocShell::FillClass( SvGlobalName* pClassName,
sal_uInt32* pFormat,
String* /* pAppName */,
String* pFullTypeName,
String* pShortTypeName,
sal_Int32 nFileFormat,
sal_Bool bTemplate /* = sal_False */) const
{
if ( nFileFormat == SOFFICE_FILEFORMAT_60 )
{
*pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
*pFormat = SOT_FORMATSTR_ID_STARCALC_60;
*pFullTypeName = String( ScResId( SCSTR_LONG_SCDOC_NAME ) );
*pShortTypeName = String( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
}
else if ( nFileFormat == SOFFICE_FILEFORMAT_8 )
{
*pClassName = SvGlobalName( SO3_SC_CLASSID_60 );
*pFormat = bTemplate ? SOT_FORMATSTR_ID_STARCALC_8_TEMPLATE : SOT_FORMATSTR_ID_STARCALC_8;
*pFullTypeName = String( RTL_CONSTASCII_USTRINGPARAM("calc8") );
*pShortTypeName = String( ScResId( SCSTR_SHORT_SCDOC_NAME ) );
}
else
{
DBG_ERROR("wat fuer ne Version?");
}
}
//------------------------------------------------------------------
void ScDocShell::DoEnterHandler()
{
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if (pViewSh)
if (pViewSh->GetViewData()->GetDocShell() == this)
SC_MOD()->InputEnterHandler();
}
//------------------------------------------------------------------
SCTAB ScDocShell::GetSaveTab()
{
SCTAB nTab = 0;
ScTabViewShell* pSh = GetBestViewShell();
if (pSh)
{
const ScMarkData& rMark = pSh->GetViewData()->GetMarkData();
for ( nTab = 0; nTab <= MAXTAB; nTab++ ) // erste markierte Tabelle
if ( rMark.GetTableSelect( nTab ) )
break;
}
return nTab;
}
sal_uInt16 ScDocShell::GetHiddenInformationState( sal_uInt16 nStates )
{
// get global state like HIDDENINFORMATION_DOCUMENTVERSIONS
sal_uInt16 nState = SfxObjectShell::GetHiddenInformationState( nStates );
if ( nStates & HIDDENINFORMATION_RECORDEDCHANGES )
{
if ( aDocument.GetChangeTrack() && aDocument.GetChangeTrack()->GetFirst() )
nState |= HIDDENINFORMATION_RECORDEDCHANGES;
}
if ( nStates & HIDDENINFORMATION_NOTES )
{
SCTAB nTableCount = aDocument.GetTableCount();
SCTAB nTable = 0;
sal_Bool bFound(sal_False);
while ( nTable < nTableCount && !bFound )
{
ScCellIterator aCellIter( &aDocument, 0,0, nTable, MAXCOL,MAXROW, nTable );
for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell && !bFound; pCell = aCellIter.GetNext() )
if (pCell->HasNote())
bFound = sal_True;
nTable++;
}
if (bFound)
nState |= HIDDENINFORMATION_NOTES;
}
return nState;
}
void ScDocShell::BeforeXMLLoading()
{
aDocument.DisableIdle( sal_True );
// prevent unnecessary broadcasts and updates
DBG_ASSERT(pModificator == NULL, "The Modificator should not exist");
pModificator = new ScDocShellModificator( *this );
aDocument.SetImportingXML( sal_True );
aDocument.EnableExecuteLink( false ); // #i101304# to be safe, prevent nested loading from external references
aDocument.EnableUndo( sal_False );
// prevent unnecessary broadcasts and "half way listeners"
aDocument.SetInsertingFromOtherDoc( sal_True );
if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
ScColumn::bDoubleAlloc = sal_True;
}
void ScDocShell::AfterXMLLoading(sal_Bool bRet)
{
if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
{
UpdateLinks();
// don't prevent establishing of listeners anymore
aDocument.SetInsertingFromOtherDoc( sal_False );
if ( bRet )
{
ScChartListenerCollection* pChartListener = aDocument.GetChartListenerCollection();
if (pChartListener)
pChartListener->UpdateDirtyCharts();
// #95582#; set the table names of linked tables to the new path
SCTAB nTabCount = aDocument.GetTableCount();
for (SCTAB i = 0; i < nTabCount; ++i)
{
if (aDocument.IsLinked( i ))
{
String aName;
aDocument.GetName(i, aName);
String aLinkTabName = aDocument.GetLinkTab(i);
xub_StrLen nLinkTabNameLength = aLinkTabName.Len();
xub_StrLen nNameLength = aName.Len();
if (nLinkTabNameLength < nNameLength)
{
// remove the quottes on begin and end of the docname and restore the escaped quotes
const sal_Unicode* pNameBuffer = aName.GetBuffer();
if ( *pNameBuffer == '\'' && // all docnames have to have a ' character on the first pos
ScGlobal::UnicodeStrChr( pNameBuffer, SC_COMPILER_FILE_TAB_SEP ) )
{
rtl::OUStringBuffer aDocURLBuffer;
sal_Bool bQuote = sal_True; // Dokumentenname ist immer quoted
++pNameBuffer;
while ( bQuote && *pNameBuffer )
{
if ( *pNameBuffer == '\'' && *(pNameBuffer-1) != '\\' )
bQuote = sal_False;
else if( !(*pNameBuffer == '\\' && *(pNameBuffer+1) == '\'') )
aDocURLBuffer.append(*pNameBuffer); // falls escaped Quote: nur Quote in den Namen
++pNameBuffer;
}
if( *pNameBuffer == SC_COMPILER_FILE_TAB_SEP ) // after the last quote of the docname should be the # char
{
xub_StrLen nIndex = nNameLength - nLinkTabNameLength;
INetURLObject aINetURLObject(aDocURLBuffer.makeStringAndClear());
if( aName.Equals(aLinkTabName, nIndex, nLinkTabNameLength) &&
(aName.GetChar(nIndex - 1) == '#') && // before the table name should be the # char
!aINetURLObject.HasError()) // the docname should be a valid URL
{
aName = ScGlobal::GetDocTabName( aDocument.GetLinkDoc( i ), aDocument.GetLinkTab( i ) );
aDocument.RenameTab(i, aName, sal_True, sal_True);
}
// else; nothing has to happen, because it is a user given name
}
// else; nothing has to happen, because it is a user given name
}
// else; nothing has to happen, because it is a user given name
}
// else; nothing has to happen, because it is a user given name
}
}
// #i94570# DataPilot table names have to be unique, or the tables can't be accessed by API.
// If no name (or an invalid name, skipped in ScXMLDataPilotTableContext::EndElement) was set, create a new name.
ScDPCollection* pDPCollection = aDocument.GetDPCollection();
if ( pDPCollection )
{
sal_uInt16 nDPCount = pDPCollection->GetCount();
for (sal_uInt16 nDP=0; nDP<nDPCount; nDP++)
{
ScDPObject* pDPObj = (*pDPCollection)[nDP];
if ( !pDPObj->GetName().Len() )
pDPObj->SetName( pDPCollection->CreateNewName() );
}
}
}
ScColumn::bDoubleAlloc = sal_False;
}
else
aDocument.SetInsertingFromOtherDoc( sal_False );
aDocument.SetImportingXML( sal_False );
aDocument.EnableExecuteLink( true );
aDocument.EnableUndo( sal_True );
bIsEmpty = sal_False;
if (pModificator)
{
delete pModificator;
pModificator = NULL;
}
else
{
DBG_ERROR("The Modificator should exist");
}
aDocument.DisableIdle( sal_False );
}
sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "sb99857", "ScDocShell::LoadXML" );
// MacroCallMode is no longer needed, state is kept in SfxObjectShell now
// no Seek(0) here - always loading from storage, GetInStream must not be called
BeforeXMLLoading();
// #i62677# BeforeXMLLoading is also called from ScXMLImport::startDocument when invoked
// from an external component. The XMLFromWrapper flag is only set here, when called
// through ScDocShell.
aDocument.SetXMLFromWrapper( sal_True );
ScXMLImportWrapper aImport( aDocument, pLoadMedium, xStor );
sal_Bool bRet(sal_False);
ErrCode nError = ERRCODE_NONE;
if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
bRet = aImport.Import(sal_False, nError);
else
bRet = aImport.Import(sal_True, nError);
if ( nError )
pLoadMedium->SetError( nError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
aDocument.SetXMLFromWrapper( sal_False );
AfterXMLLoading(bRet);
//! row heights...
return bRet;
}
sal_Bool ScDocShell::SaveXML( SfxMedium* pSaveMedium, const ::com::sun::star::uno::Reference< ::com::sun::star::embed::XStorage >& xStor )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "sb99857", "ScDocShell::SaveXML" );
aDocument.DisableIdle( sal_True );
ScXMLImportWrapper aImport( aDocument, pSaveMedium, xStor );
sal_Bool bRet(sal_False);
if (GetCreateMode() != SFX_CREATE_MODE_ORGANIZER)
bRet = aImport.Export(sal_False);
else
bRet = aImport.Export(sal_True);
aDocument.DisableIdle( sal_False );
return bRet;
}
sal_Bool __EXPORT ScDocShell::Load( SfxMedium& rMedium )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::Load" );
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
// only the latin script language is loaded
// -> initialize the others from options (before loading)
InitOptions(true);
GetUndoManager()->Clear();
sal_Bool bRet = SfxObjectShell::Load( rMedium );
if( bRet )
{
if (GetMedium())
{
SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
}
{
// prepare a valid document for XML filter
// (for ConvertFrom, InitNew is called before)
aDocument.MakeTable(0);
aDocument.GetStyleSheetPool()->CreateStandardStyles();
aDocument.UpdStlShtPtrsFrmNms();
bRet = LoadXML( &rMedium, NULL );
}
}
if (!bRet && !rMedium.GetError())
rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
if (rMedium.GetError())
SetError( rMedium.GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
InitItems();
CalcOutputFactor();
// #73762# invalidate eventually temporary table areas
if ( bRet )
aDocument.InvalidateTableArea();
bIsEmpty = sal_False;
FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
return bRet;
}
void __EXPORT ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint )
{
if (rHint.ISA(ScTablesHint) )
{
const ScTablesHint& rScHint = static_cast< const ScTablesHint& >( rHint );
if (rScHint.GetId() == SC_TAB_INSERTED)
{
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor();
if ( xVbaEvents.is() ) try
{
uno::Sequence< uno::Any > aArgs( 1 );
aArgs[0] <<= rScHint.GetTab1();
xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs );
}
catch( uno::Exception& )
{
}
}
}
if (rHint.ISA(SfxSimpleHint)) // ohne Parameter
{
sal_uLong nSlot = ((const SfxSimpleHint&)rHint).GetId();
switch ( nSlot )
{
case SFX_HINT_TITLECHANGED:
aDocument.SetName( SfxShell::GetName() );
// RegisterNewTargetNames gibts nicht mehr
SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DOCNAME_CHANGED )); // Navigator
break;
}
}
else if (rHint.ISA(SfxStyleSheetHint)) // Vorlagen geaendert
NotifyStyle((const SfxStyleSheetHint&) rHint);
else if (rHint.ISA(ScAutoStyleHint))
{
//! direct call for AutoStyles
// this is called synchronously from ScInterpreter::ScStyle,
// modifying the document must be asynchronous
// (handled by AddInitial)
ScAutoStyleHint& rStlHint = (ScAutoStyleHint&)rHint;
ScRange aRange = rStlHint.GetRange();
String aName1 = rStlHint.GetStyle1();
String aName2 = rStlHint.GetStyle2();
sal_uInt32 nTimeout = rStlHint.GetTimeout();
if (!pAutoStyleList)
pAutoStyleList = new ScAutoStyleList(this);
pAutoStyleList->AddInitial( aRange, aName1, nTimeout, aName2 );
}
else if ( rHint.ISA( SfxEventHint ) )
{
sal_uLong nEventId = ((SfxEventHint&)rHint).GetEventId();
switch ( nEventId )
{
case SFX_EVENT_LOADFINISHED:
{
// the readonly documents should not be opened in shared mode
if ( HasSharedXMLFlagSet() && !SC_MOD()->IsInSharedDocLoading() && !IsReadOnly() )
{
if ( SwitchToShared( sal_True, sal_False ) )
{
ScViewData* pViewData = GetViewData();
ScTabView* pTabView = ( pViewData ? dynamic_cast< ScTabView* >( pViewData->GetView() ) : NULL );
if ( pTabView )
{
pTabView->UpdateLayerLocks();
}
}
else
{
// switching to shared mode has failed, the document should be opened readonly
// TODO/LATER: And error message should be shown here probably
SetReadOnlyUI( sal_True );
}
}
}
break;
case SFX_EVENT_VIEWCREATED:
{
if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() )
{
ScAppOptions aAppOptions = SC_MOD()->GetAppOptions();
if ( aAppOptions.GetShowSharedDocumentWarning() )
{
WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
ScGlobal::GetRscString( STR_SHARED_DOC_WARNING ) );
aBox.SetDefaultCheckBoxText();
aBox.Execute();
sal_Bool bChecked = aBox.GetCheckBoxState();
if ( bChecked )
{
aAppOptions.SetShowSharedDocumentWarning( !bChecked );
SC_MOD()->SetAppOptions( aAppOptions );
}
}
}
try
{
uno::Reference< uno::XComponentContext > xContext;
uno::Reference< lang::XMultiServiceFactory > xServiceManager = ::comphelper::getProcessServiceFactory();
uno::Reference< beans::XPropertySet > xProp( xServiceManager, uno::UNO_QUERY_THROW );
xProp->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) >>= xContext;
if ( xContext.is() )
{
uno::Reference< container::XContentEnumerationAccess > xEnumAccess( xServiceManager, uno::UNO_QUERY_THROW );
uno::Reference< container::XEnumeration> xEnum = xEnumAccess->createContentEnumeration(
::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocumentJob" ) ) );
if ( xEnum.is() )
{
while ( xEnum->hasMoreElements() )
{
uno::Any aAny = xEnum->nextElement();
uno::Reference< lang::XSingleComponentFactory > xFactory;
aAny >>= xFactory;
if ( xFactory.is() )
{
uno::Reference< task::XJob > xJob( xFactory->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
uno::Sequence< beans::NamedValue > aArgsForJob(1);
ScViewData* pViewData = GetViewData();
SfxViewShell* pViewShell = ( pViewData ? pViewData->GetViewShell() : NULL );
SfxViewFrame* pViewFrame = ( pViewShell ? pViewShell->GetViewFrame() : NULL );
SfxFrame* pFrame = ( pViewFrame ? &pViewFrame->GetFrame() : NULL );
uno::Reference< frame::XController > xController = ( pFrame ? pFrame->GetController() : 0 );
uno::Reference< sheet::XSpreadsheetView > xSpreadsheetView( xController, uno::UNO_QUERY_THROW );
aArgsForJob[0] = beans::NamedValue( ::rtl::OUString::createFromAscii( "SpreadsheetView" ),
uno::makeAny( xSpreadsheetView ) );
xJob->execute( aArgsForJob );
}
}
}
}
}
catch ( uno::Exception & )
{
}
}
break;
case SFX_EVENT_SAVEDOC:
{
if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
{
bool bSuccess = false;
bool bRetry = true;
while ( bRetry )
{
bRetry = false;
uno::Reference< frame::XModel > xModel;
try
{
// load shared file
xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
// check if shared flag is set in shared file
bool bShared = false;
ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
ScDocShell* pSharedDocShell = ( pDocObj ? dynamic_cast< ScDocShell* >( pDocObj->GetObjectShell() ) : NULL );
if ( pSharedDocShell )
{
bShared = pSharedDocShell->HasSharedXMLFlagSet();
}
// #i87870# check if shared status was disabled and enabled again
bool bOwnEntry = false;
bool bEntriesNotAccessible = false;
try
{
::svt::ShareControlFile aControlFile( GetSharedFileURL() );
bOwnEntry = aControlFile.HasOwnEntry();
}
catch ( uno::Exception& )
{
bEntriesNotAccessible = true;
}
if ( bShared && bOwnEntry )
{
uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
if ( xStorable->isReadonly() )
{
xCloseable->close( sal_True );
String aUserName( ScGlobal::GetRscString( STR_UNKNOWN_USER ) );
bool bNoLockAccess = false;
try
{
::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
uno::Sequence< ::rtl::OUString > aData = aLockFile.GetLockData();
if ( aData.getLength() > LOCKFILE_SYSUSERNAME_ID )
{
if ( aData[LOCKFILE_OOOUSERNAME_ID].getLength() > 0 )
{
aUserName = aData[LOCKFILE_OOOUSERNAME_ID];
}
else if ( aData[LOCKFILE_SYSUSERNAME_ID].getLength() > 0 )
{
aUserName = aData[LOCKFILE_SYSUSERNAME_ID];
}
}
}
catch ( uno::Exception& )
{
bNoLockAccess = true;
}
if ( bNoLockAccess )
{
// TODO/LATER: in future an error regarding impossibility to open file for writing could be shown
ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
}
else
{
String aMessage( ScGlobal::GetRscString( STR_FILE_LOCKED_SAVE_LATER ) );
aMessage.SearchAndReplaceAscii( "%1", aUserName );
WarningBox aBox( GetActiveDialogParent(), WinBits( WB_RETRY_CANCEL | WB_DEF_RETRY ), aMessage );
if ( aBox.Execute() == RET_RETRY )
{
bRetry = true;
}
}
}
else
{
// merge changes from shared file into temp file
bool bSaveToShared = false;
if ( pSharedDocShell )
{
bSaveToShared = MergeSharedDocument( pSharedDocShell );
}
// close shared file
xCloseable->close( sal_True );
// TODO: keep file lock on shared file
// store to shared file
if ( bSaveToShared )
{
bool bChangedViewSettings = false;
ScChangeViewSettings* pChangeViewSet = aDocument.GetChangeViewSettings();
if ( pChangeViewSet && pChangeViewSet->ShowChanges() )
{
pChangeViewSet->SetShowChanges( sal_False );
pChangeViewSet->SetShowAccepted( sal_False );
aDocument.SetChangeViewSettings( *pChangeViewSet );
bChangedViewSettings = true;
}
uno::Reference< frame::XStorable > xStor( GetModel(), uno::UNO_QUERY_THROW );
// TODO/LATER: More entries from the MediaDescriptor might be interesting for the merge
uno::Sequence< beans::PropertyValue > aValues(1);
aValues[0].Name = ::rtl::OUString::createFromAscii( "FilterName" );
aValues[0].Value <<= ::rtl::OUString( GetMedium()->GetFilter()->GetFilterName() );
SFX_ITEMSET_ARG( GetMedium()->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False);
if ( pPasswordItem && pPasswordItem->GetValue().Len() )
{
aValues.realloc( 2 );
aValues[1].Name = ::rtl::OUString::createFromAscii( "Password" );
aValues[1].Value <<= ::rtl::OUString( pPasswordItem->GetValue() );
}
SC_MOD()->SetInSharedDocSaving( true );
xStor->storeToURL( GetSharedFileURL(), aValues );
SC_MOD()->SetInSharedDocSaving( false );
if ( bChangedViewSettings )
{
pChangeViewSet->SetShowChanges( sal_True );
pChangeViewSet->SetShowAccepted( sal_True );
aDocument.SetChangeViewSettings( *pChangeViewSet );
}
}
bSuccess = true;
GetUndoManager()->Clear();
}
}
else
{
xCloseable->close( sal_True );
if ( bEntriesNotAccessible )
{
// TODO/LATER: in future an error regarding impossibility to write to share control file could be shown
ErrorHandler::HandleError( ERRCODE_IO_GENERAL );
}
else
{
WarningBox aBox( GetActiveDialogParent(), WinBits( WB_OK ),
ScGlobal::GetRscString( STR_DOC_NOLONGERSHARED ) );
aBox.Execute();
SfxBindings* pBindings = GetViewBindings();
if ( pBindings )
{
pBindings->ExecuteSynchron( SID_SAVEASDOC );
}
}
}
}
catch ( uno::Exception& )
{
DBG_ERROR( "SFX_EVENT_SAVEDOC: caught exception\n" );
SC_MOD()->SetInSharedDocSaving( false );
try
{
uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
xClose->close( sal_True );
}
catch ( uno::Exception& )
{
}
}
}
if ( !bSuccess )
SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process
}
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(true);
}
break;
case SFX_EVENT_SAVEASDOC:
case SFX_EVENT_SAVETODOC:
// #i108978# If no event is sent before saving, there will also be no "...DONE" event,
// and SAVE/SAVEAS can't be distinguished from SAVETO. So stream copying is only enabled
// if there is a SAVE/SAVEAS/SAVETO event first.
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(true);
break;
case SFX_EVENT_SAVEDOCDONE:
{
if ( IsDocShared() && !SC_MOD()->IsInSharedDocSaving() )
{
}
UseSheetSaveEntries(); // use positions from saved file for next saving
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(false);
}
break;
case SFX_EVENT_SAVEASDOCDONE:
// new positions are used after "save" and "save as", but not "save to"
UseSheetSaveEntries(); // use positions from saved file for next saving
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(false);
break;
case SFX_EVENT_SAVETODOCDONE:
// only reset the flag, don't use the new positions
if (pSheetSaveData)
pSheetSaveData->SetInSupportedSave(false);
break;
default:
{
}
break;
}
}
}
// Inhalte fuer Organizer laden
sal_Bool __EXPORT ScDocShell::LoadFrom( SfxMedium& rMedium )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::LoadFrom" );
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
WaitObject aWait( GetActiveDialogParent() );
sal_Bool bRet = sal_False;
if (GetMedium())
{
SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
}
// until loading/saving only the styles in XML is implemented,
// load the whole file
bRet = LoadXML( &rMedium, NULL );
InitItems();
SfxObjectShell::LoadFrom( rMedium );
return bRet;
}
static void lcl_parseHtmlFilterOption(const OUString& rOption, LanguageType& rLang, bool& rDateConvert)
{
OUStringBuffer aBuf;
OUString aTokens[2];
sal_Int32 n = rOption.getLength();
const sal_Unicode* p = rOption.getStr();
sal_Int32 nTokenId = 0;
for (sal_Int32 i = 0; i < n; ++i)
{
const sal_Unicode c = p[i];
if (c == sal_Unicode(' '))
{
if (aBuf.getLength())
aTokens[nTokenId++] = aBuf.makeStringAndClear();
}
else
aBuf.append(c);
if (nTokenId >= 2)
break;
}
if (aBuf.getLength())
aTokens[nTokenId] = aBuf.makeStringAndClear();
rLang = static_cast<LanguageType>(aTokens[0].toInt32());
rDateConvert = static_cast<bool>(aTokens[1].toInt32());
}
namespace {
class LoadMediumGuard
{
public:
explicit LoadMediumGuard(ScDocument* pDoc) :
mpDoc(pDoc)
{
mpDoc->SetLoadingMedium(true);
}
~LoadMediumGuard()
{
mpDoc->SetLoadingMedium(false);
}
private:
ScDocument* mpDoc;
};
}
sal_Bool __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertFrom" );
LoadMediumGuard aLoadGuard(&aDocument);
sal_Bool bRet = sal_False; // sal_False heisst Benutzerabbruch !!
// bei Fehler: Fehler am Stream setzen!!
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
GetUndoManager()->Clear();
// ob nach dem Import optimale Spaltenbreiten gesetzt werden sollen
sal_Bool bSetColWidths = sal_False;
sal_Bool bSetSimpleTextColWidths = sal_False;
sal_Bool bSimpleColWidth[MAXCOLCOUNT];
memset( bSimpleColWidth, 1, (MAXCOLCOUNT) * sizeof(sal_Bool) );
ScRange aColWidthRange;
// ob nach dem Import optimale Zeilenhoehen gesetzt werden sollen
sal_Bool bSetRowHeights = sal_False;
aConvFilterName.Erase(); //@ #BugId 54198
// Alle Filter brauchen die komplette Datei am Stueck (nicht asynchron),
// darum vorher per CreateFileStream dafuer sorgen, dass die komplette
// Datei uebertragen wird.
rMedium.GetPhysicalName(); //! CreateFileStream direkt rufen, wenn verfuegbar
SFX_ITEMSET_ARG( rMedium.GetItemSet(), pUpdateDocItem, SfxUInt16Item, SID_UPDATEDOCMODE, sal_False);
nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : com::sun::star::document::UpdateDocMode::NO_UPDATE;
const SfxFilter* pFilter = rMedium.GetFilter();
if (pFilter)
{
String aFltName = pFilter->GetFilterName();
aConvFilterName=aFltName; //@ #BugId 54198
sal_Bool bCalc3 = ( aFltName.EqualsAscii(pFilterSc30) );
sal_Bool bCalc4 = ( aFltName.EqualsAscii(pFilterSc40) );
if (!bCalc3 && !bCalc4)
aDocument.SetInsertingFromOtherDoc( sal_True );
if (aFltName.EqualsAscii(pFilterXML))
bRet = LoadXML( &rMedium, NULL );
else if (aFltName.EqualsAscii(pFilterSc10))
{
SvStream* pStream = rMedium.GetInStream();
if (pStream)
{
FltError eError = ScFormatFilter::Get().ScImportStarCalc10( *pStream, &aDocument );
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
else
bRet = sal_True;
}
}
else if (aFltName.EqualsAscii(pFilterLotus))
{
String sItStr;
SfxItemSet* pSet = rMedium.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sItStr = ((const SfxStringItem*)pItem)->GetValue();
}
if (sItStr.Len() == 0)
{
// default for lotus import (from API without options):
// IBM_437 encoding
sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_437 );
}
ScColumn::bDoubleAlloc = sal_True;
FltError eError = ScFormatFilter::Get().ScImportLotus123( rMedium, &aDocument,
ScGlobal::GetCharsetValue(sItStr));
ScColumn::bDoubleAlloc = sal_False;
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
bRet = sal_True;
}
else
bRet = sal_True;
bSetColWidths = sal_True;
bSetRowHeights = sal_True;
}
else if ( aFltName.EqualsAscii(pFilterExcel4) || aFltName.EqualsAscii(pFilterExcel5) ||
aFltName.EqualsAscii(pFilterExcel95) || aFltName.EqualsAscii(pFilterExcel97) ||
aFltName.EqualsAscii(pFilterEx4Temp) || aFltName.EqualsAscii(pFilterEx5Temp) ||
aFltName.EqualsAscii(pFilterEx95Temp) || aFltName.EqualsAscii(pFilterEx97Temp) )
{
EXCIMPFORMAT eFormat = EIF_AUTO;
if ( aFltName.EqualsAscii(pFilterExcel4) || aFltName.EqualsAscii(pFilterEx4Temp) )
eFormat = EIF_BIFF_LE4;
else if ( aFltName.EqualsAscii(pFilterExcel5) || aFltName.EqualsAscii(pFilterExcel95) ||
aFltName.EqualsAscii(pFilterEx5Temp) || aFltName.EqualsAscii(pFilterEx95Temp) )
eFormat = EIF_BIFF5;
else if ( aFltName.EqualsAscii(pFilterExcel97) || aFltName.EqualsAscii(pFilterEx97Temp) )
eFormat = EIF_BIFF8;
MakeDrawLayer(); //! im Filter
CalcOutputFactor(); // #93255# prepare update of row height
ScColumn::bDoubleAlloc = sal_True;
FltError eError = ScFormatFilter::Get().ScImportExcel( rMedium, &aDocument, eFormat );
ScColumn::bDoubleAlloc = sal_False;
aDocument.UpdateFontCharSet();
if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
aDocument.UpdateChartListenerCollection(); //! fuer alle Importe?
// #75299# all graphics objects must have names
aDocument.EnsureGraphicNames();
if (eError == SCWARN_IMPORT_RANGE_OVERFLOW)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
bRet = sal_True;
}
else if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
else
bRet = sal_True;
// #93255# update of row height done inside of Excel filter to speed up chart import
// bSetRowHeights = sal_True; // #75357# optimal row heights must be updated
}
else if (aFltName.EqualsAscii(pFilterAscii))
{
SfxItemSet* pSet = rMedium.GetItemSet();
const SfxPoolItem* pItem;
ScAsciiOptions aOptions;
sal_Bool bOptInit = sal_False;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
aOptions.ReadFromString( ((const SfxStringItem*)pItem)->GetValue() );
bOptInit = sal_True;
}
if ( !bOptInit )
{
// default for ascii import (from API without options):
// ISO8859-1/MS_1252 encoding, comma, double quotes
aOptions.SetCharSet( RTL_TEXTENCODING_MS_1252 );
aOptions.SetFieldSeps( (sal_Unicode) ',' );
aOptions.SetTextSep( (sal_Unicode) '"' );
}
FltError eError = eERR_OK;
sal_Bool bOverflow = sal_False;
if( ! rMedium.IsStorage() )
{
ScImportExport aImpEx( &aDocument );
aImpEx.SetExtOptions( aOptions );
SvStream* pInStream = rMedium.GetInStream();
if (pInStream)
{
pInStream->SetStreamCharSet( aOptions.GetCharSet() );
pInStream->Seek( 0 );
bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL() );
eError = bRet ? eERR_OK : SCERR_IMPORT_CONNECT;
aDocument.StartAllListeners();
aDocument.SetDirty();
bOverflow = aImpEx.IsOverflow();
}
else
{
DBG_ERROR( "No Stream" );
}
}
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
else if ( bOverflow )
{
if (!GetError())
SetError(SCWARN_IMPORT_RANGE_OVERFLOW, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
bSetColWidths = sal_True;
bSetSimpleTextColWidths = sal_True;
}
else if (aFltName.EqualsAscii(pFilterDBase))
{
String sItStr;
SfxItemSet* pSet = rMedium.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sItStr = ((const SfxStringItem*)pItem)->GetValue();
}
if (sItStr.Len() == 0)
{
// default for dBase import (from API without options):
// IBM_850 encoding
sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
}
sal_uLong eError = DBaseImport( rMedium.GetPhysicalName(),
ScGlobal::GetCharsetValue(sItStr), bSimpleColWidth );
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW );
}
else
bRet = sal_True;
aColWidthRange.aStart.SetRow( 1 ); // Spaltenheader nicht
bSetColWidths = sal_True;
bSetSimpleTextColWidths = sal_True;
// Memo-Felder fuehren zu einem bSimpleColWidth[nCol]==FALSE
for ( SCCOL nCol=0; nCol <= MAXCOL && !bSetRowHeights; nCol++ )
{
if ( !bSimpleColWidth[nCol] )
bSetRowHeights = sal_True;
}
}
else if (aFltName.EqualsAscii(pFilterDif))
{
SvStream* pStream = rMedium.GetInStream();
if (pStream)
{
FltError eError;
String sItStr;
SfxItemSet* pSet = rMedium.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sItStr = ((const SfxStringItem*)pItem)->GetValue();
}
if (sItStr.Len() == 0)
{
// default for DIF import (from API without options):
// ISO8859-1/MS_1252 encoding
sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
}
eError = ScFormatFilter::Get().ScImportDif( *pStream, &aDocument, ScAddress(0,0,0),
ScGlobal::GetCharsetValue(sItStr));
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
bRet = sal_True;
}
else
bRet = sal_True;
}
bSetColWidths = sal_True;
bSetSimpleTextColWidths = sal_True;
bSetRowHeights = sal_True;
}
else if (aFltName.EqualsAscii(pFilterSylk))
{
FltError eError = SCERR_IMPORT_UNKNOWN;
if( !rMedium.IsStorage() )
{
ScImportExport aImpEx( &aDocument );
SvStream* pInStream = rMedium.GetInStream();
if (pInStream)
{
pInStream->Seek( 0 );
bRet = aImpEx.ImportStream( *pInStream, rMedium.GetBaseURL(), SOT_FORMATSTR_ID_SYLK );
eError = bRet ? eERR_OK : SCERR_IMPORT_UNKNOWN;
aDocument.StartAllListeners();
aDocument.SetDirty();
}
else
{
DBG_ERROR( "No Stream" );
}
}
if ( eError != eERR_OK && !GetError() )
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
bSetColWidths = sal_True;
bSetSimpleTextColWidths = sal_True;
bSetRowHeights = sal_True;
}
else if (aFltName.EqualsAscii(pFilterQPro6))
{
ScColumn::bDoubleAlloc = sal_True;
FltError eError = ScFormatFilter::Get().ScImportQuattroPro( rMedium, &aDocument);
ScColumn::bDoubleAlloc = sal_False;
if (eError != eERR_OK)
{
if (!GetError())
SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
bRet = sal_True;
}
else
bRet = sal_True;
// TODO: Filter should set column widths. Not doing it here, it may
// result in very narrow or wide columns, depending on content.
// Setting row heights makes cells with font size attribution or
// wrapping enabled look nicer..
bSetRowHeights = sal_True;
}
else if (aFltName.EqualsAscii(pFilterRtf))
{
FltError eError = SCERR_IMPORT_UNKNOWN;
if( !rMedium.IsStorage() )
{
SvStream* pInStream = rMedium.GetInStream();
if (pInStream)
{
pInStream->Seek( 0 );
ScRange aRange;
eError = ScFormatFilter::Get().ScImportRTF( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange );
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
bRet = sal_True;
}
else
bRet = sal_True;
aDocument.StartAllListeners();
aDocument.SetDirty();
bSetColWidths = sal_True;
bSetRowHeights = sal_True;
}
else
{
DBG_ERROR( "No Stream" );
}
}
if ( eError != eERR_OK && !GetError() )
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
else if (aFltName.EqualsAscii(pFilterHtml) || aFltName.EqualsAscii(pFilterHtmlWebQ))
{
FltError eError = SCERR_IMPORT_UNKNOWN;
sal_Bool bWebQuery = aFltName.EqualsAscii(pFilterHtmlWebQ);
if( !rMedium.IsStorage() )
{
SvStream* pInStream = rMedium.GetInStream();
if (pInStream)
{
LanguageType eLang = LANGUAGE_SYSTEM;
bool bDateConvert = false;
SfxItemSet* pSet = rMedium.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
String aFilterOption = (static_cast<const SfxStringItem*>(pItem))->GetValue();
lcl_parseHtmlFilterOption(aFilterOption, eLang, bDateConvert);
}
pInStream->Seek( 0 );
ScRange aRange;
// HTML macht eigenes ColWidth/RowHeight
CalcOutputFactor();
SvNumberFormatter aNumFormatter(aDocument.GetServiceManager(), eLang);
eError = ScFormatFilter::Get().ScImportHTML( *pInStream, rMedium.GetBaseURL(), &aDocument, aRange,
GetOutputFactor(), !bWebQuery, &aNumFormatter, bDateConvert );
if (eError != eERR_OK)
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK )
bRet = sal_True;
}
else
bRet = sal_True;
aDocument.StartAllListeners();
aDocument.SetDirty();
}
else
{
DBG_ERROR( "No Stream" );
}
}
if ( eError != eERR_OK && !GetError() )
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
else
{
if (!GetError())
SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
if (!bCalc3)
aDocument.SetInsertingFromOtherDoc( sal_False );
}
else
{
DBG_ERROR("Kein Filter bei ConvertFrom");
}
InitItems();
CalcOutputFactor();
if ( bRet && (bSetColWidths || bSetRowHeights) )
{ // Spaltenbreiten/Zeilenhoehen anpassen, Basis 100% Zoom
Fraction aZoom( 1, 1 );
double nPPTX = ScGlobal::nScreenPPTX * (double) aZoom
/ GetOutputFactor(); // Faktor ist Drucker zu Bildschirm
double nPPTY = ScGlobal::nScreenPPTY * (double) aZoom;
VirtualDevice aVirtDev;
// all sheets (for Excel import)
SCTAB nTabCount = aDocument.GetTableCount();
for (SCTAB nTab=0; nTab<nTabCount; nTab++)
{
SCCOL nEndCol;
SCROW nEndRow;
aDocument.GetCellArea( nTab, nEndCol, nEndRow );
aColWidthRange.aEnd.SetCol( nEndCol );
aColWidthRange.aEnd.SetRow( nEndRow );
ScMarkData aMark;
aMark.SetMarkArea( aColWidthRange );
aMark.MarkToMulti();
// Reihenfolge erst Breite dann Hoehe ist wichtig (vergl. hund.rtf)
if ( bSetColWidths )
{
for ( SCCOL nCol=0; nCol <= nEndCol; nCol++ )
{
sal_uInt16 nWidth = aDocument.GetOptimalColWidth(
nCol, nTab, &aVirtDev, nPPTX, nPPTY, aZoom, aZoom, sal_False, &aMark,
(bSetSimpleTextColWidths && bSimpleColWidth[nCol]) );
aDocument.SetColWidth( nCol, nTab,
nWidth + (sal_uInt16)ScGlobal::nLastColWidthExtra );
}
}
// if ( bSetRowHeights )
// {
// // nExtra must be 0
// aDocument.SetOptimalHeight( 0, nEndRow, nTab, 0, &aVirtDev,
// nPPTX, nPPTY, aZoom, aZoom, sal_False );
// }
}
if ( bSetRowHeights )
UpdateAllRowHeights(); // with vdev or printer, depending on configuration
}
FinishedLoading( SFX_LOADED_MAINDOCUMENT | SFX_LOADED_IMAGES );
GetUndoManager()->Clear();
// #73762# invalidate eventually temporary table areas
if ( bRet )
aDocument.InvalidateTableArea();
bIsEmpty = sal_False;
return bRet;
}
ScDocShell::PrepareSaveGuard::PrepareSaveGuard( ScDocShell& rDocShell )
: mrDocShell( rDocShell)
{
// DoEnterHandler not here (because of AutoSave), is in ExecuteSave.
ScChartListenerCollection* pCharts = mrDocShell.aDocument.GetChartListenerCollection();
if (pCharts)
pCharts->UpdateDirtyCharts(); // Charts to be updated.
mrDocShell.aDocument.StopTemporaryChartLock();
if (mrDocShell.pAutoStyleList)
mrDocShell.pAutoStyleList->ExecuteAllNow(); // Execute template timeouts now.
if (mrDocShell.aDocument.HasExternalRefManager())
{
ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
if (pRefMgr && pRefMgr->hasExternalData())
{
pRefMgr->setAllCacheTableReferencedStati( false);
mrDocShell.aDocument.MarkUsedExternalReferences(); // Mark tables of external references to be written.
}
}
if (mrDocShell.GetCreateMode()== SFX_CREATE_MODE_STANDARD)
mrDocShell.SfxObjectShell::SetVisArea( Rectangle() ); // "Normally" worked on => no VisArea.
}
ScDocShell::PrepareSaveGuard::~PrepareSaveGuard()
{
if (mrDocShell.aDocument.HasExternalRefManager())
{
ScExternalRefManager* pRefMgr = mrDocShell.aDocument.GetExternalRefManager();
if (pRefMgr && pRefMgr->hasExternalData())
{
// Prevent accidental data loss due to lack of knowledge.
pRefMgr->setAllCacheTableReferencedStati( true);
}
}
}
sal_Bool __EXPORT ScDocShell::Save()
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::Save" );
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
PrepareSaveGuard aPrepareGuard( *this);
// wait cursor is handled with progress bar
sal_Bool bRet = SfxObjectShell::Save();
if( bRet )
bRet = SaveXML( GetMedium(), NULL );
return bRet;
}
sal_Bool __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::SaveAs" );
#if ENABLE_SHEET_PROTECTION
ScTabViewShell* pViewShell = GetBestViewShell();
if (pViewShell && ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_OOO))
{
if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_OOO))
// password re-type cancelled. Don't save the document.
return false;
}
#endif
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
PrepareSaveGuard aPrepareGuard( *this);
aDocument.setDocAccTitle(String());
// SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst( this, TYPE(SfxTopViewFrame));
SfxViewFrame* pFrame1 = SfxViewFrame::GetFirst( this );
if (pFrame1)
{
Window* pWindow = &pFrame1->GetWindow();
if ( pWindow )
{
Window* pSysWin = pWindow->GetSystemWindow();
if ( pSysWin )
{
pSysWin->SetAccessibleName(String());
}
}
}
// wait cursor is handled with progress bar
sal_Bool bRet = SfxObjectShell::SaveAs( rMedium );
if( bRet )
bRet = SaveXML( &rMedium, NULL );
return bRet;
}
sal_Bool __EXPORT ScDocShell::IsInformationLost()
{
/*
const SfxFilter *pFilt = GetMedium()->GetFilter();
sal_Bool bRet = pFilt && pFilt->IsAlienFormat() && bNoInformLost;
if (bNoInformLost) // nur einmal!!
bNoInformLost = sal_False;
return bRet;
*/
//!!! bei Gelegenheit ein korrekte eigene Behandlung einbauen
return SfxObjectShell::IsInformationLost();
}
// Xcl-like column width measured in characters of standard font.
xub_StrLen lcl_ScDocShell_GetColWidthInChars( sal_uInt16 nWidth )
{
// double fColScale = 1.0;
double f = nWidth;
f *= 1328.0 / 25.0;
f += 90.0;
f *= 1.0 / 23.0;
// f /= fColScale * 256.0;
f /= 256.0;
return xub_StrLen( f );
}
void lcl_ScDocShell_GetFixedWidthString( String& rStr, const ScDocument& rDoc,
SCTAB nTab, SCCOL nCol, sal_Bool bValue, SvxCellHorJustify eHorJust )
{
xub_StrLen nLen = lcl_ScDocShell_GetColWidthInChars(
rDoc.GetColWidth( nCol, nTab ) );
if ( nLen < rStr.Len() )
{
if ( bValue )
rStr.AssignAscii( "###" );
rStr.Erase( nLen );
}
if ( nLen > rStr.Len() )
{
if ( bValue && eHorJust == SVX_HOR_JUSTIFY_STANDARD )
eHorJust = SVX_HOR_JUSTIFY_RIGHT;
switch ( eHorJust )
{
case SVX_HOR_JUSTIFY_RIGHT:
{
String aTmp;
aTmp.Fill( nLen - rStr.Len() );
rStr.Insert( aTmp, 0 );
}
break;
case SVX_HOR_JUSTIFY_CENTER:
{
xub_StrLen nLen2 = (nLen - rStr.Len()) / 2;
String aTmp;
aTmp.Fill( nLen2 );
rStr.Insert( aTmp, 0 );
rStr.Expand( nLen );
}
break;
default:
rStr.Expand( nLen );
}
}
}
void lcl_ScDocShell_WriteEmptyFixedWidthString( SvStream& rStream,
const ScDocument& rDoc, SCTAB nTab, SCCOL nCol )
{
String aString;
lcl_ScDocShell_GetFixedWidthString( aString, rDoc, nTab, nCol, sal_False,
SVX_HOR_JUSTIFY_STANDARD );
rStream.WriteUnicodeOrByteText( aString );
}
void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt )
{
sal_Unicode cDelim = rAsciiOpt.nFieldSepCode;
sal_Unicode cStrDelim = rAsciiOpt.nTextSepCode;
CharSet eCharSet = rAsciiOpt.eCharSet;
sal_Bool bFixedWidth = rAsciiOpt.bFixedWidth;
sal_Bool bSaveAsShown = rAsciiOpt.bSaveAsShown;
CharSet eOldCharSet = rStream.GetStreamCharSet();
rStream.SetStreamCharSet( eCharSet );
sal_uInt16 nOldNumberFormatInt = rStream.GetNumberFormatInt();
ByteString aStrDelimEncoded; // only used if not Unicode
UniString aStrDelimDecoded; // only used if context encoding
ByteString aDelimEncoded;
UniString aDelimDecoded;
sal_Bool bContextOrNotAsciiEncoding;
if ( eCharSet == RTL_TEXTENCODING_UNICODE )
{
rStream.StartWritingUnicodeText();
bContextOrNotAsciiEncoding = sal_False;
}
else
{
aStrDelimEncoded = ByteString( cStrDelim, eCharSet );
aDelimEncoded = ByteString( cDelim, eCharSet );
rtl_TextEncodingInfo aInfo;
aInfo.StructSize = sizeof(aInfo);
if ( rtl_getTextEncodingInfo( eCharSet, &aInfo ) )
{
bContextOrNotAsciiEncoding =
(((aInfo.Flags & RTL_TEXTENCODING_INFO_CONTEXT) != 0) ||
((aInfo.Flags & RTL_TEXTENCODING_INFO_ASCII) == 0));
if ( bContextOrNotAsciiEncoding )
{
aStrDelimDecoded = String( aStrDelimEncoded, eCharSet );
aDelimDecoded = String( aDelimEncoded, eCharSet );
}
}
else
bContextOrNotAsciiEncoding = sal_False;
}
SCCOL nStartCol = 0;
SCROW nStartRow = 0;
SCTAB nTab = GetSaveTab();
SCCOL nEndCol;
SCROW nEndRow;
aDocument.GetCellArea( nTab, nEndCol, nEndRow );
ScProgress aProgress( this, ScGlobal::GetRscString( STR_SAVE_DOC ), nEndRow );
String aString;
ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell, SfxViewShell::Current());
const ScViewOptions& rOpt = (pViewSh)
? pViewSh->GetViewData()->GetOptions()
: aDocument.GetViewOptions();
sal_Bool bShowFormulas = rOpt.GetOption( VOPT_FORMULAS );
sal_Bool bTabProtect = aDocument.IsTabProtected( nTab );
SCCOL nCol;
SCROW nRow;
SCCOL nNextCol = nStartCol;
SCROW nNextRow = nStartRow;
SCCOL nEmptyCol;
SCROW nEmptyRow;
SvNumberFormatter& rFormatter = *aDocument.GetFormatTable();
ScHorizontalCellIterator aIter( &aDocument, nTab, nStartCol, nStartRow,
nEndCol, nEndRow );
ScBaseCell* pCell;
while ( ( pCell = aIter.GetNext( nCol, nRow ) ) != NULL )
{
sal_Bool bProgress = sal_False; // only upon line change
if ( nNextRow < nRow )
{ // empty rows or/and empty columns up to end of row
bProgress = sal_True;
for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
{ // remaining columns of last row
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
endlub( rStream );
nNextRow++;
for ( nEmptyRow = nNextRow; nEmptyRow < nRow; nEmptyRow++ )
{ // completely empty rows
for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
{
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
endlub( rStream );
}
for ( nEmptyCol = nStartCol; nEmptyCol < nCol; nEmptyCol++ )
{ // empty columns at beginning of row
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
nNextRow = nRow;
}
else if ( nNextCol < nCol )
{ // empty columns in same row
for ( nEmptyCol = nNextCol; nEmptyCol < nCol; nEmptyCol++ )
{ // columns in between
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
}
if ( nCol == nEndCol )
{
bProgress = sal_True;
nNextCol = nStartCol;
nNextRow = nRow + 1;
}
else
nNextCol = nCol + 1;
CellType eType = pCell->GetCellType();
if ( bTabProtect )
{
const ScProtectionAttr* pProtAttr =
(const ScProtectionAttr*) aDocument.GetAttr(
nCol, nRow, nTab, ATTR_PROTECTION );
if ( pProtAttr->GetHideCell() ||
( eType == CELLTYPE_FORMULA && bShowFormulas &&
pProtAttr->GetHideFormula() ) )
eType = CELLTYPE_NONE; // hide
}
sal_Bool bString;
switch ( eType )
{
case CELLTYPE_NOTE:
case CELLTYPE_NONE:
aString.Erase();
bString = sal_False;
break;
case CELLTYPE_FORMULA :
{
sal_uInt16 nErrCode;
if ( bShowFormulas )
{
((ScFormulaCell*)pCell)->GetFormula( aString );
bString = sal_True;
}
else if ( ( nErrCode = ((ScFormulaCell*)pCell)->GetErrCode() ) != 0 )
{
aString = ScGlobal::GetErrorString( nErrCode );
bString = sal_True;
}
else if ( ((ScFormulaCell*)pCell)->IsValue() )
{
sal_uInt32 nFormat;
aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
if ( bFixedWidth || bSaveAsShown )
{
Color* pDummy;
ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
}
else
{
ScCellFormat::GetInputString( pCell, nFormat, aString, rFormatter );
bString = sal_False;
}
}
else
{
if ( bSaveAsShown )
{
sal_uInt32 nFormat;
aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
Color* pDummy;
ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
}
else
((ScFormulaCell*)pCell)->GetString( aString );
bString = sal_True;
}
}
break;
case CELLTYPE_STRING :
if ( bSaveAsShown )
{
sal_uInt32 nFormat;
aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
Color* pDummy;
ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
}
else
((ScStringCell*)pCell)->GetString( aString );
bString = sal_True;
break;
case CELLTYPE_EDIT :
{
const EditTextObject* pObj;
static_cast<const ScEditCell*>(pCell)->GetData( pObj);
EditEngine& rEngine = aDocument.GetEditEngine();
rEngine.SetText( *pObj);
aString = rEngine.GetText(); // including LF
bString = sal_True;
}
break;
case CELLTYPE_VALUE :
{
sal_uInt32 nFormat;
aDocument.GetNumberFormat( nCol, nRow, nTab, nFormat );
if ( bFixedWidth || bSaveAsShown )
{
Color* pDummy;
ScCellFormat::GetString( pCell, nFormat, aString, &pDummy, rFormatter );
bString = bSaveAsShown && rFormatter.IsTextFormat( nFormat);
}
else
{
ScCellFormat::GetInputString( pCell, nFormat, aString, rFormatter );
bString = sal_False;
}
}
break;
default:
DBG_ERROR( "ScDocShell::AsciiSave: unknown CellType" );
aString.Erase();
bString = sal_False;
}
if ( bFixedWidth )
{
SvxCellHorJustify eHorJust = (SvxCellHorJustify)
((const SvxHorJustifyItem*) aDocument.GetAttr( nCol, nRow,
nTab, ATTR_HOR_JUSTIFY ))->GetValue();
lcl_ScDocShell_GetFixedWidthString( aString, aDocument, nTab, nCol,
!bString, eHorJust );
rStream.WriteUnicodeOrByteText( aString );
}
else
{
if (!bString && cStrDelim != 0 && aString.Len() > 0)
{
sal_Unicode c = aString.GetChar(0);
bString = (c == cStrDelim || c == ' ' ||
aString.GetChar( aString.Len()-1) == ' ' ||
aString.Search( cStrDelim) != STRING_NOTFOUND);
if (!bString && cDelim != 0)
bString = (aString.Search( cDelim) != STRING_NOTFOUND);
}
if ( bString )
{
if ( cStrDelim != 0 ) //@ BugId 55355
{
if ( eCharSet == RTL_TEXTENCODING_UNICODE )
{
xub_StrLen nPos = aString.Search( cStrDelim );
// #i116636# quotes are needed if text delimiter (quote), field delimiter, or LF is in the cell text
bool bNeedQuotes = rAsciiOpt.bQuoteAllText ||
( nPos != STRING_NOTFOUND ) ||
( aString.Search( cDelim ) != STRING_NOTFOUND ) ||
( aString.Search( sal_Unicode(_LF) ) != STRING_NOTFOUND );
while ( nPos != STRING_NOTFOUND )
{
aString.Insert( cStrDelim, nPos );
nPos = aString.Search( cStrDelim, nPos+2 );
}
if ( bNeedQuotes )
rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
rStream.WriteUnicodeText( aString );
if ( bNeedQuotes )
rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
}
else
{
// #105549# This is nasty. The Unicode to byte encoding
// may convert typographical quotation marks to ASCII
// quotation marks, which may interfer with the delimiter,
// so we have to escape delimiters after the string has
// been encoded. Since this may happen also with UTF-8
// encoded typographical quotation marks if such was
// specified as a delimiter we have to check for the full
// encoded delimiter string, not just one character.
// Now for RTL_TEXTENCODING_ISO_2022_... and similar brain
// dead encodings where one code point (and especially a
// low ASCII value) may represent different characters, we
// have to convert forth and back and forth again. Same for
// UTF-7 since it is a context sensitive encoding too.
if ( bContextOrNotAsciiEncoding )
{
// to byte encoding
ByteString aStrEnc( aString, eCharSet );
// back to Unicode
UniString aStrDec( aStrEnc, eCharSet );
// search on re-decoded string
xub_StrLen nPos = aStrDec.Search( aStrDelimDecoded );
bool bNeedQuotes = rAsciiOpt.bQuoteAllText ||
( nPos != STRING_NOTFOUND ) ||
( aStrDec.Search( aDelimDecoded ) != STRING_NOTFOUND ) ||
( aStrDec.Search( sal_Unicode(_LF) ) != STRING_NOTFOUND );
while ( nPos != STRING_NOTFOUND )
{
aStrDec.Insert( aStrDelimDecoded, nPos );
nPos = aStrDec.Search( aStrDelimDecoded,
nPos+1+aStrDelimDecoded.Len() );
}
// write byte re-encoded
if ( bNeedQuotes )
rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
rStream.WriteUnicodeOrByteText( aStrDec, eCharSet );
if ( bNeedQuotes )
rStream.WriteUniOrByteChar( cStrDelim, eCharSet );
}
else
{
ByteString aStrEnc( aString, eCharSet );
// search on encoded string
xub_StrLen nPos = aStrEnc.Search( aStrDelimEncoded );
bool bNeedQuotes = rAsciiOpt.bQuoteAllText ||
( nPos != STRING_NOTFOUND ) ||
( aStrEnc.Search( aDelimEncoded ) != STRING_NOTFOUND ) ||
( aStrEnc.Search( sal_Char(_LF) ) != STRING_NOTFOUND );
while ( nPos != STRING_NOTFOUND )
{
aStrEnc.Insert( aStrDelimEncoded, nPos );
nPos = aStrEnc.Search( aStrDelimEncoded,
nPos+1+aStrDelimEncoded.Len() );
}
// write byte encoded
if ( bNeedQuotes )
rStream.Write( aStrDelimEncoded.GetBuffer(),
aStrDelimEncoded.Len() );
rStream.Write( aStrEnc.GetBuffer(), aStrEnc.Len() );
if ( bNeedQuotes )
rStream.Write( aStrDelimEncoded.GetBuffer(),
aStrDelimEncoded.Len() );
}
}
}
else
rStream.WriteUnicodeOrByteText( aString );
}
else
rStream.WriteUnicodeOrByteText( aString );
}
if( nCol < nEndCol )
{
if(cDelim!=0) //@ BugId 55355
rStream.WriteUniOrByteChar( cDelim );
}
else
endlub( rStream );
if ( bProgress )
aProgress.SetStateOnPercent( nRow );
}
// write out empty if requested
if ( nNextRow <= nEndRow )
{
for ( nEmptyCol = nNextCol; nEmptyCol < nEndCol; nEmptyCol++ )
{ // remaining empty columns of last row
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
endlub( rStream );
nNextRow++;
}
for ( nEmptyRow = nNextRow; nEmptyRow <= nEndRow; nEmptyRow++ )
{ // entire empty rows
for ( nEmptyCol = nStartCol; nEmptyCol < nEndCol; nEmptyCol++ )
{
if ( bFixedWidth )
lcl_ScDocShell_WriteEmptyFixedWidthString( rStream,
aDocument, nTab, nEmptyCol );
else if ( cDelim != 0 )
rStream.WriteUniOrByteChar( cDelim );
}
endlub( rStream );
}
rStream.SetStreamCharSet( eOldCharSet );
rStream.SetNumberFormatInt( nOldNumberFormatInt );
}
sal_Bool __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed )
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertTo" );
ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() );
// #i6500# don't call DoEnterHandler here (doesn't work with AutoSave),
// it's already in ExecuteSave (as for Save and SaveAs)
if (pAutoStyleList)
pAutoStyleList->ExecuteAllNow(); // Vorlagen-Timeouts jetzt ausfuehren
if (GetCreateMode()== SFX_CREATE_MODE_STANDARD)
SfxObjectShell::SetVisArea( Rectangle() ); // normal bearbeitet -> keine VisArea
DBG_ASSERT( rMed.GetFilter(), "Filter == 0" );
sal_Bool bRet = sal_False;
String aFltName = rMed.GetFilter()->GetFilterName();
/*
if (aFltName.EqualsAscii(pFilterLotus))
{
SvStream* pStream = rMed.GetOutStream();
if (pStream)
{
FltError eError = ScFormatFilter::Get().ScExportLotus123( *pStream, &aDocument, ExpWK1,
CHARSET_IBMPC_437 );
bRet = eError == eERR_OK;
}
}
else
*/
if (aFltName.EqualsAscii(pFilterXML))
{
//TODO/LATER: this shouldn't happen!
DBG_ERROR("XML filter in ConvertFrom?!");
bRet = SaveXML( &rMed, NULL );
}
else if (aFltName.EqualsAscii(pFilterExcel5) || aFltName.EqualsAscii(pFilterExcel95) ||
aFltName.EqualsAscii(pFilterExcel97) || aFltName.EqualsAscii(pFilterEx5Temp) ||
aFltName.EqualsAscii(pFilterEx95Temp) || aFltName.EqualsAscii(pFilterEx97Temp) ||
aFltName.EqualsAscii(pFilterEx07Xml))
{
WaitObject aWait( GetActiveDialogParent() );
bool bDoSave = true;
if( ScTabViewShell* pViewShell = GetBestViewShell() )
{
ScExtDocOptions* pExtDocOpt = aDocument.GetExtDocOptions();
if( !pExtDocOpt )
aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions );
pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt );
/* #115980# #i104990# If the imported document contains a medium
password, determine if we can save it, otherwise ask the users
whether they want to save without it. */
if( (rMed.GetFilter()->GetFilterFlags() & SFX_FILTER_ENCRYPTION) == 0 )
{
SfxItemSet* pItemSet = rMed.GetItemSet();
const SfxPoolItem* pItem = 0;
if( pItemSet && pItemSet->GetItemState( SID_PASSWORD, sal_True, &pItem ) == SFX_ITEM_SET )
{
bDoSave = ScWarnPassword::WarningOnPassword( rMed );
// #i42858# remove password from medium (warn only one time)
if( bDoSave )
pItemSet->ClearItem( SID_PASSWORD );
}
}
#if ENABLE_SHEET_PROTECTION
if( bDoSave )
{
bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen( aDocument, PASSHASH_XL );
bDoSave = !bNeedRetypePassDlg || pViewShell->ExecuteRetypePassDlg( PASSHASH_XL );
}
#endif
}
if( bDoSave )
{
ExportFormatExcel eFormat = ExpBiff5;
if( aFltName.EqualsAscii( pFilterExcel97 ) || aFltName.EqualsAscii( pFilterEx97Temp ) )
eFormat = ExpBiff8;
if( aFltName.EqualsAscii( pFilterEx07Xml ) )
eFormat = Exp2007Xml;
FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 );
if( eError && !GetError() )
SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
// don't return false for warnings
bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK);
}
else
{
// export aborted, i.e. "Save without password" warning
SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
else if (aFltName.EqualsAscii(pFilterAscii))
{
SvStream* pStream = rMed.GetOutStream();
if (pStream)
{
String sItStr;
SfxItemSet* pSet = rMed.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sItStr = ((const SfxStringItem*)pItem)->GetValue();
}
if ( sItStr.Len() == 0 )
{
// default for ascii export (from API without options):
// ISO8859-1/MS_1252 encoding, comma, double quotes
ScImportOptions aDefOptions( ',', '"', RTL_TEXTENCODING_MS_1252 );
sItStr = aDefOptions.BuildString();
}
WaitObject aWait( GetActiveDialogParent() );
ScImportOptions aOptions( sItStr );
AsciiSave( *pStream, aOptions );
bRet = sal_True;
if (aDocument.GetTableCount() > 1)
if (!rMed.GetError())
rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
}
else if (aFltName.EqualsAscii(pFilterDBase))
{
String sCharSet;
SfxItemSet* pSet = rMed.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sCharSet = ((const SfxStringItem*)pItem)->GetValue();
}
if (sCharSet.Len() == 0)
{
// default for dBase export (from API without options):
// IBM_850 encoding
sCharSet = ScGlobal::GetCharsetString( RTL_TEXTENCODING_IBM_850 );
}
WaitObject aWait( GetActiveDialogParent() );
// HACK damit Sba geoffnetes TempFile ueberschreiben kann
rMed.CloseOutStream();
sal_Bool bHasMemo = sal_False;
sal_uLong eError = DBaseExport( rMed.GetPhysicalName(),
ScGlobal::GetCharsetValue(sCharSet), bHasMemo );
if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) )
{
//! if ( !rMed.GetError() )
//! rMed.SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
eError = eERR_OK;
}
//! else if ( aDocument.GetTableCount() > 1 && !rMed.GetError() )
//! rMed.SetError( SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE );
if ( bHasMemo )
aTmpFile.setExtension( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("dbt")) );
if ( eError != eERR_OK )
{
if (!GetError())
SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
if ( bHasMemo && IsDocument( aTmpFile ) )
KillFile( aTmpFile );
}
else
{
bRet = sal_True;
if ( bHasMemo )
{
SfxStringItem* pNameItem =
(SfxStringItem*) rMed.GetItemSet()->GetItem( SID_FILE_NAME );
INetURLObject aDbtFile( pNameItem->GetValue(), INET_PROT_FILE );
aDbtFile.setExtension( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("dbt")) );
if ( IsDocument( aDbtFile ) && !KillFile( aDbtFile ) )
bRet = sal_False;
if ( bRet && !MoveFile( aTmpFile, aDbtFile ) )
bRet = sal_False;
if ( !bRet )
{
KillFile( aTmpFile );
if ( !GetError() )
SetError( SCERR_EXPORT_DATA, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
}
}
else if (aFltName.EqualsAscii(pFilterDif))
{
SvStream* pStream = rMed.GetOutStream();
if (pStream)
{
String sItStr;
SfxItemSet* pSet = rMed.GetItemSet();
const SfxPoolItem* pItem;
if ( pSet && SFX_ITEM_SET ==
pSet->GetItemState( SID_FILE_FILTEROPTIONS, sal_True, &pItem ) )
{
sItStr = ((const SfxStringItem*)pItem)->GetValue();
}
if (sItStr.Len() == 0)
{
// default for DIF export (from API without options):
// ISO8859-1/MS_1252 encoding
sItStr = ScGlobal::GetCharsetString( RTL_TEXTENCODING_MS_1252 );
}
WaitObject aWait( GetActiveDialogParent() );
ScFormatFilter::Get().ScExportDif( *pStream, &aDocument, ScAddress(0,0,0),
ScGlobal::GetCharsetValue(sItStr) );
bRet = sal_True;
if (aDocument.GetTableCount() > 1)
if (!rMed.GetError())
rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ));
}
}
else if (aFltName.EqualsAscii(pFilterSylk))
{
SvStream* pStream = rMed.GetOutStream();
if ( pStream )
{
WaitObject aWait( GetActiveDialogParent() );
SCCOL nEndCol;
SCROW nEndRow;
aDocument.GetCellArea( 0, nEndCol, nEndRow );
ScRange aRange( 0,0,0, nEndCol,nEndRow,0 );
ScImportExport aImExport( &aDocument, aRange );
aImExport.SetFormulas( sal_True );
bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_SYLK );
}
}
else if (aFltName.EqualsAscii(pFilterHtml))
{
SvStream* pStream = rMed.GetOutStream();
if ( pStream )
{
WaitObject aWait( GetActiveDialogParent() );
ScImportExport aImExport( &aDocument );
aImExport.SetStreamPath( rMed.GetName() );
bRet = aImExport.ExportStream( *pStream, rMed.GetBaseURL( true ), SOT_FORMATSTR_ID_HTML );
if ( bRet && aImExport.GetNonConvertibleChars().Len() )
SetError( *new StringErrorInfo(
SCWARN_EXPORT_NONCONVERTIBLE_CHARS,
aImExport.GetNonConvertibleChars(),
ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
}
else
{
if (GetError())
SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) );
}
return bRet;
}
sal_Bool __EXPORT ScDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor )
{
return SfxObjectShell::SaveCompleted( xStor );
}
sal_Bool __EXPORT ScDocShell::DoSaveCompleted( SfxMedium * pNewStor )
{
sal_Bool bRet = SfxObjectShell::DoSaveCompleted( pNewStor );
// SC_HINT_DOC_SAVED fuer Wechsel ReadOnly -> Read/Write
Broadcast( SfxSimpleHint( SC_HINT_DOC_SAVED ) );
return bRet;
}
sal_Bool ScDocShell::QuerySlotExecutable( sal_uInt16 nSlotId )
{
// #i112634# ask VBA event handlers whether to save or print the document
using namespace ::com::sun::star::script::vba;
sal_Int32 nVbaEventId = VBAEventId::NO_EVENT;
uno::Sequence< uno::Any > aArgs;
switch( nSlotId )
{
case SID_SAVEDOC:
case SID_SAVEASDOC:
nVbaEventId = VBAEventId::WORKBOOK_BEFORESAVE;
aArgs.realloc( 1 );
aArgs[ 0 ] <<= (nSlotId == SID_SAVEASDOC);
break;
case SID_PRINTDOC:
case SID_PRINTDOCDIRECT:
nVbaEventId = VBAEventId::WORKBOOK_BEFOREPRINT;
break;
}
sal_Bool bSlotExecutable = sal_True;
if( nVbaEventId != VBAEventId::NO_EVENT ) try
{
uno::Reference< XVBAEventProcessor > xEventProcessor( aDocument.GetVbaEventProcessor(), uno::UNO_QUERY_THROW );
xEventProcessor->processVbaEvent( nVbaEventId, aArgs );
}
catch( util::VetoException& )
{
bSlotExecutable = sal_False;
}
catch( uno::Exception& )
{
}
return bSlotExecutable;
}
sal_uInt16 __EXPORT ScDocShell::PrepareClose( sal_Bool bUI, sal_Bool bForBrowsing )
{
if(SC_MOD()->GetCurRefDlgId()>0)
{
SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this );
if( pFrame )
{
SfxViewShell* p = pFrame->GetViewShell();
ScTabViewShell* pViewSh = PTR_CAST(ScTabViewShell,p);
if(pViewSh!=NULL)
{
Window *pWin=pViewSh->GetWindow();
if(pWin!=NULL) pWin->GrabFocus();
}
}
return sal_False;
}
if ( aDocument.IsInLinkUpdate() || aDocument.IsInInterpreter() )
{
ErrorMessage(STR_CLOSE_ERROR_LINK);
return sal_False;
}
DoEnterHandler();
// start 'Workbook_BeforeClose' VBA event handler for possible veto
if( !IsInPrepareClose() )
{
try
{
uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( aDocument.GetVbaEventProcessor(), uno::UNO_SET_THROW );
uno::Sequence< uno::Any > aArgs;
xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_BEFORECLOSE, aArgs );
}
catch( util::VetoException& )
{
// if event processor throws VetoException, macro has vetoed close
return sal_False;
}
catch( uno::Exception& )
{
}
}
// end handler code
sal_uInt16 nRet = SfxObjectShell::PrepareClose( bUI, bForBrowsing );
if (nRet == sal_True) // sal_True = schliessen
aDocument.DisableIdle(sal_True); // nicht mehr drin rumpfuschen !!!
return nRet;
}
void ScDocShell::PrepareReload()
{
SfxObjectShell::PrepareReload(); // tut nichts?
// Das Disconnect von DDE-Links kann Reschedule ausloesen.
// Wenn die DDE-Links erst im Dokument-dtor geloescht werden, kann beim Reload
// aus diesem Reschedule das DDE-Link-Update fuer das neue Dokument ausgeloest
// werden. Dabei verklemmt sicht dann irgendwas.
// -> Beim Reload die DDE-Links des alten Dokuments vorher disconnecten
aDocument.DisconnectDdeLinks();
}
String ScDocShell::GetOwnFilterName() // static
{
return String::CreateFromAscii(pFilterSc50);
}
String ScDocShell::GetHtmlFilterName()
{
return String::CreateFromAscii(pFilterHtml);
}
String ScDocShell::GetWebQueryFilterName() // static
{
return String::CreateFromAscii(pFilterHtmlWebQ);
}
String ScDocShell::GetAsciiFilterName() // static
{
return String::CreateFromAscii(pFilterAscii);
}
String ScDocShell::GetLotusFilterName() // static
{
return String::CreateFromAscii(pFilterLotus);
}
String ScDocShell::GetDBaseFilterName() // static
{
return String::CreateFromAscii(pFilterDBase);
}
String ScDocShell::GetDifFilterName() // static
{
return String::CreateFromAscii(pFilterDif);
}
sal_Bool ScDocShell::HasAutomaticTableName( const String& rFilter ) // static
{
// sal_True for those filters that keep the default table name
// (which is language specific)
return rFilter.EqualsAscii( pFilterAscii )
|| rFilter.EqualsAscii( pFilterLotus )
|| rFilter.EqualsAscii( pFilterExcel4 )
|| rFilter.EqualsAscii( pFilterEx4Temp )
|| rFilter.EqualsAscii( pFilterDBase )
|| rFilter.EqualsAscii( pFilterDif )
|| rFilter.EqualsAscii( pFilterSylk )
|| rFilter.EqualsAscii( pFilterHtml )
|| rFilter.EqualsAscii( pFilterRtf );
}
//==================================================================
#define __SCDOCSHELL_INIT \
aDocument ( SCDOCMODE_DOCUMENT, this ), \
aDdeTextFmt(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("TEXT"))), \
nPrtToScreenFactor( 1.0 ), \
pImpl ( new DocShell_Impl ), \
bHeaderOn ( sal_True ), \
bFooterOn ( sal_True ), \
bNoInformLost ( sal_True ), \
bIsEmpty ( sal_True ), \
bIsInUndo ( sal_False ), \
bDocumentModifiedPending( sal_False ), \
nDocumentLock ( 0 ), \
nCanUpdate (com::sun::star::document::UpdateDocMode::ACCORDING_TO_CONFIG), \
bUpdateEnabled ( sal_True ), \
pOldAutoDBRange ( NULL ), \
pDocHelper ( NULL ), \
pAutoStyleList ( NULL ), \
pPaintLockData ( NULL ), \
pOldJobSetup ( NULL ), \
pSolverSaveData ( NULL ), \
pSheetSaveData ( NULL ), \
pModificator ( NULL )
//------------------------------------------------------------------
ScDocShell::ScDocShell( const ScDocShell& rShell )
: SvRefBase(),
SotObject(),
SfxObjectShell( rShell.GetCreateMode() ),
SfxListener(),
__SCDOCSHELL_INIT
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ScDocShell" );
SetPool( &SC_MOD()->GetPool() );
bIsInplace = rShell.bIsInplace;
pDocFunc = new ScDocFunc(*this);
// SetBaseModel needs exception handling
ScModelObj::CreateAndSet( this );
StartListening(*this);
SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
if (pStlPool)
StartListening(*pStlPool);
GetPageOnFromPageStyleSet( NULL, 0, bHeaderOn, bFooterOn );
SetHelpId( HID_SCSHELL_DOCSH );
// InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
}
//------------------------------------------------------------------
ScDocShell::ScDocShell( const sal_uInt64 i_nSfxCreationFlags )
: SfxObjectShell( i_nSfxCreationFlags )
, __SCDOCSHELL_INIT
{
RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ScDocShell" );
SetPool( &SC_MOD()->GetPool() );
bIsInplace = (GetCreateMode() == SFX_CREATE_MODE_EMBEDDED);
// wird zurueckgesetzt, wenn nicht inplace
// #118840# set flag at ScDocument that it is used temporary (e.g. inplace
// for transporting a chart over the clipboard)
if(bIsInplace)
{
aDocument.mbIsTemporary = true;
}
pDocFunc = new ScDocFunc(*this);
// SetBaseModel needs exception handling
ScModelObj::CreateAndSet( this );
StartListening(*this);
SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
if (pStlPool)
StartListening(*pStlPool);
SetHelpId( HID_SCSHELL_DOCSH );
aDocument.GetDBCollection()->SetRefreshHandler(
LINK( this, ScDocShell, RefreshDBDataHdl ) );
// InitItems und CalcOutputFactor werden jetzt nach bei Load/ConvertFrom/InitNew gerufen
}
//------------------------------------------------------------------
__EXPORT ScDocShell::~ScDocShell()
{
ResetDrawObjectShell(); // #55570# falls der Drawing-Layer noch versucht, darauf zuzugreifen
SfxStyleSheetPool* pStlPool = aDocument.GetStyleSheetPool();
if (pStlPool)
EndListening(*pStlPool);
EndListening(*this);
delete pAutoStyleList;
SfxApplication *pSfxApp = SFX_APP();
if ( pSfxApp->GetDdeService() ) // DDE vor Dokument loeschen
pSfxApp->RemoveDdeTopic( this );
delete pDocFunc;
delete aDocument.mpUndoManager;
aDocument.mpUndoManager = 0;
delete pImpl;
delete pPaintLockData;
delete pOldJobSetup; // gesetzt nur bei Fehler in StartJob()
delete pSolverSaveData;
delete pSheetSaveData;
delete pOldAutoDBRange;
if (pModificator)
{
DBG_ERROR("The Modificator should not exist");
delete pModificator;
}
}
//------------------------------------------------------------------
::svl::IUndoManager* __EXPORT ScDocShell::GetUndoManager()
{
return aDocument.GetUndoManager();
}
void ScDocShell::SetModified( sal_Bool bModified )
{
if ( SfxObjectShell::IsEnableSetModified() )
{
SfxObjectShell::SetModified( bModified );
Broadcast( SfxSimpleHint( SFX_HINT_DOCCHANGED ) );
}
}
void ScDocShell::SetDocumentModified( sal_Bool bIsModified /* = sal_True */ )
{
// BroadcastUno muss auch mit pPaintLockData sofort passieren
//! auch bei SetDrawModified, wenn Drawing angebunden ist
//! dann eigener Hint???
if ( pPaintLockData && bIsModified )
{
// #i115009# broadcast BCA_BRDCST_ALWAYS, so a component can read recalculated results
// of RecalcModeAlways formulas (like OFFSET) after modifying cells
aDocument.Broadcast( SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS, NULL );
aDocument.InvalidateTableArea(); // #i105279# needed here
aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
pPaintLockData->SetModified(); // spaeter...
return;
}
SetDrawModified( bIsModified );
if ( bIsModified )
{
if ( aDocument.IsAutoCalcShellDisabled() )
SetDocumentModifiedPending( sal_True );
else
{
SetDocumentModifiedPending( sal_False );
aDocument.InvalidateStyleSheetUsage();
aDocument.InvalidateTableArea();
aDocument.InvalidateLastTableOpParams();
aDocument.Broadcast( SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS, NULL );
if ( aDocument.IsForcedFormulaPending() && aDocument.GetAutoCalc() )
aDocument.CalcFormulaTree( sal_True );
PostDataChanged();
// Detective AutoUpdate:
// Update if formulas were modified (DetectiveDirty) or the list contains
// "Trace Error" entries (#75362# - Trace Error can look completely different
// after changes to non-formula cells).
ScDetOpList* pList = aDocument.GetDetOpList();
if ( pList && ( aDocument.IsDetectiveDirty() || pList->HasAddError() ) &&
pList->Count() && !IsInUndo() && SC_MOD()->GetAppOptions().GetDetectiveAuto() )
{
GetDocFunc().DetectiveRefresh(sal_True); // sal_True = caused by automatic update
}
aDocument.SetDetectiveDirty(sal_False); // always reset, also if not refreshed
}
// #b6697848# notify UNO objects after BCA_BRDCST_ALWAYS etc.
aDocument.BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
}
}
// SetDrawModified - ohne Formel-Update
// (Drawing muss auch beim normalen SetDocumentModified upgedated werden,
// z.B. bei Tabelle loeschen etc.)
void ScDocShell::SetDrawModified( sal_Bool bIsModified /* = sal_True */ )
{
sal_Bool bUpdate = ( bIsModified != IsModified() );
SetModified( bIsModified );
SfxBindings* pBindings = GetViewBindings();
if (bUpdate)
{
if (pBindings)
{
pBindings->Invalidate( SID_SAVEDOC );
pBindings->Invalidate( SID_DOC_MODIFIED );
}
}
if (bIsModified)
{
if (pBindings)
{
// #i105960# Undo etc used to be volatile.
// They always have to be invalidated, including drawing layer or row height changes
// (but not while pPaintLockData is set).
pBindings->Invalidate( SID_UNDO );
pBindings->Invalidate( SID_REDO );
pBindings->Invalidate( SID_REPEAT );
}
if ( aDocument.IsChartListenerCollectionNeedsUpdate() )
{
aDocument.UpdateChartListenerCollection();
SFX_APP()->Broadcast(SfxSimpleHint( SC_HINT_DRAW_CHANGED )); // Navigator
}
SC_MOD()->AnythingChanged();
}
}
void ScDocShell::SetInUndo(sal_Bool bSet)
{
bIsInUndo = bSet;
}
void ScDocShell::GetDocStat( ScDocStat& rDocStat )
{
SfxPrinter* pPrinter = GetPrinter();
aDocument.GetDocStat( rDocStat );
rDocStat.nPageCount = 0;
if ( pPrinter )
for ( SCTAB i=0; i<rDocStat.nTableCount; i++ )
rDocStat.nPageCount = sal::static_int_cast<sal_uInt16>( rDocStat.nPageCount +
(sal_uInt16) ScPrintFunc( this, pPrinter, i ).GetTotalPages() );
}
SfxDocumentInfoDialog* __EXPORT ScDocShell::CreateDocumentInfoDialog(
Window *pParent, const SfxItemSet &rSet )
{
SfxDocumentInfoDialog* pDlg = new SfxDocumentInfoDialog( pParent, rSet );
ScDocShell* pDocSh = PTR_CAST(ScDocShell,SfxObjectShell::Current());
//nur mit Statistik, wenn dieses Doc auch angezeigt wird, nicht
//aus dem Doc-Manager
if( pDocSh == this )
{
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001
::CreateTabPage ScDocStatPageCreate = pFact->GetTabPageCreatorFunc( RID_SCPAGE_STAT );
DBG_ASSERT(ScDocStatPageCreate, "Tabpage create fail!");//CHINA001
pDlg->AddTabPage( 42,
ScGlobal::GetRscString( STR_DOC_STAT ),
ScDocStatPageCreate,
NULL);
//CHINA001 pDlg->AddTabPage( 42,
//CHINA001 ScGlobal::GetRscString( STR_DOC_STAT ),
//CHINA001 ScDocStatPage::Create,
//CHINA001 NULL );
}
return pDlg;
}
Window* ScDocShell::GetActiveDialogParent()
{
ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
if ( pViewSh )
return pViewSh->GetDialogParent();
else
return Application::GetDefDialogParent();
}
void ScDocShell::SetSolverSaveData( const ScOptSolverSave& rData )
{
delete pSolverSaveData;
pSolverSaveData = new ScOptSolverSave( rData );
}
ScSheetSaveData* ScDocShell::GetSheetSaveData()
{
if (!pSheetSaveData)
pSheetSaveData = new ScSheetSaveData;
return pSheetSaveData;
}
void ScDocShell::UseSheetSaveEntries()
{
if (pSheetSaveData)
{
pSheetSaveData->UseSaveEntries(); // use positions from saved file for next saving
bool bHasEntries = false;
SCTAB nTabCount = aDocument.GetTableCount();
SCTAB nTab;
for (nTab = 0; nTab < nTabCount; ++nTab)
if (pSheetSaveData->HasStreamPos(nTab))
bHasEntries = true;
if (!bHasEntries)
{
// if no positions were set (for example, export to other format),
// reset all "valid" flags
for (nTab = 0; nTab < nTabCount; ++nTab)
if (aDocument.IsStreamValid(nTab))
aDocument.SetStreamValid(nTab, sal_False);
}
}
}
// --- ScDocShellModificator ------------------------------------------
ScDocShellModificator::ScDocShellModificator( ScDocShell& rDS )
:
rDocShell( rDS ),
aProtector( rDS.GetDocument()->GetRefreshTimerControlAddress() )
{
ScDocument* pDoc = rDocShell.GetDocument();
bAutoCalcShellDisabled = pDoc->IsAutoCalcShellDisabled();
bIdleDisabled = pDoc->IsIdleDisabled();
pDoc->SetAutoCalcShellDisabled( sal_True );
pDoc->DisableIdle( sal_True );
}
ScDocShellModificator::~ScDocShellModificator()
{
ScDocument* pDoc = rDocShell.GetDocument();
pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
if ( !bAutoCalcShellDisabled && rDocShell.IsDocumentModifiedPending() )
rDocShell.SetDocumentModified(); // last one shuts off the lights
pDoc->DisableIdle( bIdleDisabled );
}
void ScDocShellModificator::SetDocumentModified()
{
ScDocument* pDoc = rDocShell.GetDocument();
if ( !pDoc->IsImportingXML() )
{
// AutoCalcShellDisabled temporaer restaurieren
sal_Bool bDisabled = pDoc->IsAutoCalcShellDisabled();
pDoc->SetAutoCalcShellDisabled( bAutoCalcShellDisabled );
rDocShell.SetDocumentModified();
pDoc->SetAutoCalcShellDisabled( bDisabled );
}
else
{
// uno broadcast is necessary for api to work
// -> must also be done during xml import
pDoc->BroadcastUno( SfxSimpleHint( SFX_HINT_DATACHANGED ) );
}
}
//<!--Added by PengYunQuan for Validity Cell Range Picker
sal_Bool ScDocShell::AcceptStateUpdate() const
{
if( SfxObjectShell::AcceptStateUpdate() )
return sal_True;
if( SC_MOD()->Find1RefWindow( SFX_APP()->GetTopWindow() ) )
return sal_True;
return sal_False;
}
//-->Added by PengYunQuan for Validity Cell Range Picker
bool ScDocShell::IsChangeRecording() const
{
ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
return pChangeTrack != NULL;
}
bool ScDocShell::HasChangeRecordProtection() const
{
bool bRes = false;
ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
if (pChangeTrack)
bRes = pChangeTrack->IsProtected();
return bRes;
}
void ScDocShell::SetChangeRecording( bool bActivate )
{
bool bOldChangeRecording = IsChangeRecording();
if (bActivate)
{
aDocument.StartChangeTracking();
ScChangeViewSettings aChangeViewSet;
aChangeViewSet.SetShowChanges(sal_True);
aDocument.SetChangeViewSettings(aChangeViewSet);
}
else
{
aDocument.EndChangeTracking();
PostPaintGridAll();
}
if (bOldChangeRecording != IsChangeRecording())
{
UpdateAcceptChangesDialog();
// Slots invalidieren
SfxBindings* pBindings = GetViewBindings();
if (pBindings)
pBindings->InvalidateAll(sal_False);
}
}
bool ScDocShell::SetProtectionPassword( const String &rNewPassword )
{
bool bRes = false;
ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
if (pChangeTrack)
{
sal_Bool bProtected = pChangeTrack->IsProtected();
if (rNewPassword.Len())
{
// when password protection is applied change tracking must always be active
SetChangeRecording( true );
::com::sun::star::uno::Sequence< sal_Int8 > aProtectionHash;
SvPasswordHelper::GetHashPassword( aProtectionHash, rNewPassword );
pChangeTrack->SetProtection( aProtectionHash );
}
else
{
pChangeTrack->SetProtection( ::com::sun::star::uno::Sequence< sal_Int8 >() );
}
bRes = true;
if ( bProtected != pChangeTrack->IsProtected() )
{
UpdateAcceptChangesDialog();
SetDocumentModified();
}
}
return bRes;
}
bool ScDocShell::GetProtectionHash( /*out*/ ::com::sun::star::uno::Sequence< sal_Int8 > &rPasswordHash )
{
bool bRes = false;
ScChangeTrack* pChangeTrack = aDocument.GetChangeTrack();
if (pChangeTrack && pChangeTrack->IsProtected())
{
rPasswordHash = pChangeTrack->GetProtection();
bRes = true;
}
return bRes;
}
void ScDocShell::BeforeLoading( SfxMedium& /*rMedium*/, const ::rtl::OUString & rstrTypeName, const ::rtl::OUString & /*rstrFilterName*/ )
{
const sal_uInt8 nMediumFlag = GetMediumFlag<false>( rstrTypeName );
if( nMediumFlag & E_MEDIUM_FLAG_MSXML )
{
aDocument.SetImportingMSXML( true );
if ( GetCreateMode() != SFX_CREATE_MODE_ORGANIZER )
ScColumn::bDoubleAlloc = sal_True;
}
}
void ScDocShell::AfterLoading( SfxMedium& /*rMedium*/, const ::rtl::OUString & rstrTypeName, const ::rtl::OUString & /*rstrFilterName*/ )
{
const sal_uInt8 nMediumFlag = GetMediumFlag<false>( rstrTypeName );
if( nMediumFlag & E_MEDIUM_FLAG_MSXML )
{
aDocument.SetImportingMSXML( false );
if ( GetCreateMode() != SFX_CREATE_MODE_ORGANIZER )
ScColumn::bDoubleAlloc = sal_False;
// After loading, the XEmbeddedObject was probably set modified flag, so reset the flag to false.
uno::Sequence < ::rtl::OUString > aNames = GetEmbeddedObjectContainer().GetObjectNames();
for ( sal_Int32 n = 0; n < aNames.getLength(); n++ )
{
::rtl::OUString aName = aNames[n];
uno::Reference < embed::XEmbeddedObject > xObj = GetEmbeddedObjectContainer().GetEmbeddedObject( aName );
OSL_ENSURE( xObj.is(), "An empty entry in the embedded objects list!\n" );
if ( xObj.is() )
{
try
{
sal_Int32 nState = xObj->getCurrentState();
if ( nState != embed::EmbedStates::LOADED )
{
uno::Reference< util::XModifiable > xModifiable( xObj->getComponent(), uno::UNO_QUERY );
if ( xModifiable.is() )
xModifiable->setModified(sal_False);
}
}
catch( uno::Exception& )
{}
}
}
}
}