1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/thread.h>
21 #include <osl/diagnose.h>
22 #include <sot/exchange.hxx>
23 #include <sot/formats.hxx>
24 #include <sfx2/app.hxx>
25 #include <sfx2/linkmgr.hxx>
26 #include <servobj.hxx>
30 #include <rangenam.hxx>
31 #include <unotools/charclass.hxx>
33 using namespace formula
;
35 static bool lcl_FillRangeFromName( ScRange
& rRange
, ScDocShell
* pDocSh
, const OUString
& rName
)
39 ScDocument
& rDoc
= pDocSh
->GetDocument();
40 ScRangeName
* pNames
= rDoc
.GetRangeName();
43 const ScRangeData
* pData
= pNames
->findByUpperName(ScGlobal::getCharClass().uppercase(rName
));
46 if ( pData
->IsValidReference( rRange
) )
54 ScServerObjectSvtListenerForwarder::ScServerObjectSvtListenerForwarder(
55 ScServerObject
* pObjP
)
60 ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder()
62 //! do NOT access pObj
65 void ScServerObjectSvtListenerForwarder::Notify( const SfxHint
& rHint
)
67 pObj
->Notify( aBroadcaster
, rHint
);
70 ScServerObject::ScServerObject( ScDocShell
* pShell
, const OUString
& rItem
) :
73 bRefreshListener( false )
77 if ( lcl_FillRangeFromName( aRange
, pDocSh
, rItem
) )
79 aItemStr
= rItem
; // must be parsed again on ref update
84 ScDocument
& rDoc
= pDocSh
->GetDocument();
85 SCTAB nTab
= ScDocShell::GetCurTab();
86 aRange
.aStart
.SetTab( nTab
);
88 // For DDE link, we always must parse references using OOO A1 convention.
90 if ( aRange
.Parse( rItem
, rDoc
, FormulaGrammar::CONV_OOO
) & ScRefFlags::VALID
)
94 else if ( aRange
.aStart
.Parse( rItem
, rDoc
, FormulaGrammar::CONV_OOO
) & ScRefFlags::VALID
)
97 aRange
.aEnd
= aRange
.aStart
;
101 OSL_FAIL("ScServerObject: invalid item");
105 pDocSh
->GetDocument().GetLinkManager()->InsertServer( this );
106 pDocSh
->GetDocument().StartListeningArea( aRange
, false, &aForwarder
);
108 StartListening(*pDocSh
); // to notice if DocShell gets deleted
109 StartListening(*SfxGetpApp()); // for SfxHintId::ScAreasChanged
112 ScServerObject::~ScServerObject()
117 void ScServerObject::Clear()
121 ScDocShell
* pTemp
= pDocSh
;
124 pTemp
->GetDocument().EndListeningArea(aRange
, false, &aForwarder
);
125 pTemp
->GetDocument().GetLinkManager()->RemoveServer( this );
126 EndListening(*pTemp
);
127 EndListening(*SfxGetpApp());
131 void ScServerObject::EndListeningAll()
133 aForwarder
.EndListeningAll();
134 SfxListener::EndListeningAll();
137 bool ScServerObject::GetData(
138 css::uno::Any
& rData
/*out param*/,
139 const OUString
& rMimeType
, bool /* bSynchron */ )
144 // named ranges may have changed -> update aRange
145 if ( !aItemStr
.isEmpty() )
148 if ( lcl_FillRangeFromName( aNew
, pDocSh
, aItemStr
) && aNew
!= aRange
)
151 bRefreshListener
= true;
155 if ( bRefreshListener
)
157 // refresh the listeners now (this is called from a timer)
160 pDocSh
->GetDocument().StartListeningArea( aRange
, false, &aForwarder
);
161 StartListening(*pDocSh
);
162 StartListening(*SfxGetpApp());
163 bRefreshListener
= false;
166 OUString aDdeTextFmt
= pDocSh
->GetDdeTextFmt();
167 ScDocument
& rDoc
= pDocSh
->GetDocument();
169 SotClipboardFormatId eFormatId
= SotExchange::GetFormatIdFromMimeType( rMimeType
);
170 if (SotClipboardFormatId::STRING
== eFormatId
|| SotClipboardFormatId::STRING_TSVC
== eFormatId
)
172 ScImportExport
aObj( rDoc
, aRange
);
173 if( aDdeTextFmt
[0] == 'F' )
174 aObj
.SetFormulas( true );
175 if( aDdeTextFmt
== "SYLK" || aDdeTextFmt
== "FSYLK" )
178 if( aObj
.ExportByteString( aByteData
, osl_getThreadTextEncoding(), SotClipboardFormatId::SYLK
) )
180 rData
<<= css::uno::Sequence
< sal_Int8
>(
181 reinterpret_cast<const sal_Int8
*>(aByteData
.getStr()),
182 aByteData
.getLength() + 1 );
187 if( aDdeTextFmt
== "CSV" || aDdeTextFmt
== "FCSV" )
188 aObj
.SetSeparator( ',' );
189 /* TODO: STRING_TSVC could preserve line breaks with added quotes. */
190 aObj
.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace
, ' ', false ) );
191 return aObj
.ExportData( rMimeType
, rData
);
194 ScImportExport
aObj( rDoc
, aRange
);
195 aObj
.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace
, ' ', false ) );
197 return aObj
.ExportData( rMimeType
, rData
);
201 void ScServerObject::Notify( SfxBroadcaster
& rBC
, const SfxHint
& rHint
)
203 bool bDataChanged
= false;
205 // DocShell can't be tested via type info, because SfxHintId::Dying comes from the dtor
206 if ( &rBC
== pDocSh
)
208 // from DocShell, only SfxHintId::Dying is interesting
209 if ( rHint
.GetId() == SfxHintId::Dying
)
212 EndListening(*SfxGetpApp());
213 // don't access DocShell anymore for EndListening etc.
216 else if (dynamic_cast<const SfxApplication
*>( &rBC
) != nullptr)
218 if ( !aItemStr
.isEmpty() && rHint
.GetId() == SfxHintId::ScAreasChanged
)
220 // check if named range was modified
222 if ( lcl_FillRangeFromName( aNew
, pDocSh
, aItemStr
) && aNew
!= aRange
)
228 // must be from Area broadcasters
230 if (rHint
.GetId() == SfxHintId::ScDataChanged
)
232 else if (rHint
.GetId() == SfxHintId::ScAreaChanged
) // position of broadcaster changed
234 const ScAreaChangedHint
*pChgHint
= static_cast<const ScAreaChangedHint
*>(&rHint
);
235 const ScRange
& aNewRange
= pChgHint
->GetRange();
236 if ( aRange
!= aNewRange
)
238 bRefreshListener
= true;
242 else if (rHint
.GetId() == SfxHintId::Dying
)
244 // If the range is being deleted, listening must be restarted
245 // after the deletion is complete (done in GetData)
246 bRefreshListener
= true;
251 if ( bDataChanged
&& HasDataLinks() )
252 SvLinkSource::NotifyDataChanged();
255 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */