Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include <sot/formats.hxx>
30 : : #include <sfx2/app.hxx>
31 : : #include <sfx2/linkmgr.hxx>
32 : : #include "servobj.hxx"
33 : : #include "docsh.hxx"
34 : : #include "impex.hxx"
35 : : #include "brdcst.hxx"
36 : : #include "rangenam.hxx"
37 : : #include "sc.hrc" // SC_HINT_AREAS_CHANGED
38 : :
39 : : using namespace formula;
40 : :
41 : : // -----------------------------------------------------------------------
42 : :
43 : 5 : sal_Bool lcl_FillRangeFromName( ScRange& rRange, ScDocShell* pDocSh, const String& rName )
44 : : {
45 [ + - ]: 5 : if (pDocSh)
46 : : {
47 : 5 : ScDocument* pDoc = pDocSh->GetDocument();
48 : 5 : ScRangeName* pNames = pDoc->GetRangeName();
49 [ + - ]: 5 : if (pNames)
50 : : {
51 [ + - ][ + - ]: 5 : const ScRangeData* pData = pNames->findByUpperName(ScGlobal::pCharClass->uppercase(rName));
52 [ - + ]: 5 : if (pData)
53 : : {
54 [ # # ]: 0 : if ( pData->IsValidReference( rRange ) )
55 : 0 : return sal_True;
56 : : }
57 : : }
58 : : }
59 : 5 : return false;
60 : : }
61 : :
62 : 5 : ScServerObjectSvtListenerForwarder::ScServerObjectSvtListenerForwarder(
63 : : ScServerObject* pObjP)
64 [ + - ]: 5 : : pObj(pObjP)
65 : : {
66 : 5 : }
67 : :
68 [ + - ]: 5 : ScServerObjectSvtListenerForwarder::~ScServerObjectSvtListenerForwarder()
69 : : {
70 : : //! do NOT access pObj
71 [ - + ]: 5 : }
72 : :
73 : 0 : void ScServerObjectSvtListenerForwarder::Notify( SvtBroadcaster& /* rBC */, const SfxHint& rHint)
74 : : {
75 : 0 : pObj->Notify( aBroadcaster, rHint);
76 : 0 : }
77 : :
78 : 5 : ScServerObject::ScServerObject( ScDocShell* pShell, const String& rItem ) :
79 : : aForwarder( this ),
80 : : pDocSh( pShell ),
81 [ + - ][ + - ]: 5 : bRefreshListener( false )
[ + - ]
82 : : {
83 : : // parse item string
84 : :
85 [ + - ][ - + ]: 5 : if ( lcl_FillRangeFromName( aRange, pDocSh, rItem ) )
86 : : {
87 [ # # ]: 0 : aItemStr = rItem; // must be parsed again on ref update
88 : : }
89 : : else
90 : : {
91 : : // parse ref
92 : 5 : ScDocument* pDoc = pDocSh->GetDocument();
93 [ + - ]: 5 : SCTAB nTab = pDocSh->GetCurTab();
94 : 5 : aRange.aStart.SetTab( nTab );
95 : :
96 : : // For DDE link, we always must parse references using OOO A1 convention.
97 : :
98 [ + - ][ + - ]: 5 : if ( aRange.Parse( rItem, pDoc, FormulaGrammar::CONV_OOO ) & SCA_VALID )
99 : : {
100 : : // area reference
101 : : }
102 [ + - ][ + - ]: 5 : else if ( aRange.aStart.Parse( rItem, pDoc, FormulaGrammar::CONV_OOO ) & SCA_VALID )
103 : : {
104 : : // cell reference
105 : 5 : aRange.aEnd = aRange.aStart;
106 : : }
107 : : else
108 : : {
109 : : OSL_FAIL("ScServerObject: invalid item");
110 : : }
111 : : }
112 : :
113 [ + - ][ + - ]: 5 : pDocSh->GetDocument()->GetLinkManager()->InsertServer( this );
114 [ + - ]: 5 : pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder );
115 : :
116 [ + - ]: 5 : StartListening(*pDocSh); // um mitzubekommen, wenn die DocShell geloescht wird
117 [ + - ][ + - ]: 5 : StartListening(*SFX_APP()); // for SC_HINT_AREAS_CHANGED
118 : 5 : }
119 : :
120 [ + - ][ + - ]: 5 : ScServerObject::~ScServerObject()
[ + - ]
121 : : {
122 [ + - ]: 5 : Clear();
123 [ - + ]: 10 : }
124 : :
125 : 5 : void ScServerObject::Clear()
126 : : {
127 [ + - ]: 5 : if (pDocSh)
128 : : {
129 : 5 : ScDocShell* pTemp = pDocSh;
130 : 5 : pDocSh = NULL;
131 : :
132 : 5 : pTemp->GetDocument()->EndListeningArea( aRange, &aForwarder );
133 : 5 : pTemp->GetDocument()->GetLinkManager()->RemoveServer( this );
134 : 5 : EndListening(*pTemp);
135 : 5 : EndListening(*SFX_APP());
136 : : }
137 : 5 : }
138 : :
139 : 0 : void ScServerObject::EndListeningAll()
140 : : {
141 : 0 : aForwarder.EndListeningAll();
142 : 0 : SfxListener::EndListeningAll();
143 : 0 : }
144 : :
145 : 5 : sal_Bool ScServerObject::GetData(
146 : : ::com::sun::star::uno::Any & rData /*out param*/,
147 : : const String & rMimeType, sal_Bool /* bSynchron */ )
148 : : {
149 [ - + ]: 5 : if (!pDocSh)
150 : 0 : return false;
151 : :
152 : : // named ranges may have changed -> update aRange
153 [ - + ]: 5 : if ( aItemStr.Len() )
154 : : {
155 : 0 : ScRange aNew;
156 [ # # ][ # # ]: 0 : if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
[ # # ][ # # ]
157 : : {
158 : 0 : aRange = aNew;
159 : 0 : bRefreshListener = sal_True;
160 : : }
161 : : }
162 : :
163 [ - + ]: 5 : if ( bRefreshListener )
164 : : {
165 : : // refresh the listeners now (this is called from a timer)
166 : :
167 [ # # ]: 0 : EndListeningAll();
168 [ # # ]: 0 : pDocSh->GetDocument()->StartListeningArea( aRange, &aForwarder );
169 [ # # ]: 0 : StartListening(*pDocSh);
170 [ # # ][ # # ]: 0 : StartListening(*SFX_APP());
171 : 0 : bRefreshListener = false;
172 : : }
173 : :
174 [ + - ]: 5 : String aDdeTextFmt = pDocSh->GetDdeTextFmt();
175 : 5 : ScDocument* pDoc = pDocSh->GetDocument();
176 : :
177 [ + - ][ + - ]: 5 : if( FORMAT_STRING == SotExchange::GetFormatIdFromMimeType( rMimeType ))
178 : : {
179 [ + - ]: 5 : ScImportExport aObj( pDoc, aRange );
180 [ - + ]: 5 : if( aDdeTextFmt.GetChar(0) == 'F' )
181 : 0 : aObj.SetFormulas( sal_True );
182 [ + - ][ + - ]: 10 : if( aDdeTextFmt.EqualsAscii( "SYLK" ) ||
[ - + ][ - + ]
183 [ + - ]: 5 : aDdeTextFmt.EqualsAscii( "FSYLK" ) )
184 : : {
185 : 0 : rtl::OString aByteData;
186 [ # # ][ # # ]: 0 : if( aObj.ExportByteString( aByteData, osl_getThreadTextEncoding(), SOT_FORMATSTR_ID_SYLK ) )
[ # # ]
187 : : {
188 : : rData <<= ::com::sun::star::uno::Sequence< sal_Int8 >(
189 : 0 : (const sal_Int8*)aByteData.getStr(),
190 [ # # ][ # # ]: 0 : aByteData.getLength() + 1 );
[ # # ]
191 : 0 : return 1;
192 : : }
193 : 0 : return 0;
194 : : }
195 [ + - ][ + - ]: 10 : if( aDdeTextFmt.EqualsAscii( "CSV" ) ||
[ - + ][ - + ]
196 [ + - ]: 5 : aDdeTextFmt.EqualsAscii( "FCSV" ) )
197 : 0 : aObj.SetSeparator( ',' );
198 : 5 : aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
199 [ + - ][ + - ]: 5 : return aObj.ExportData( rMimeType, rData ) ? 1 : 0;
[ + - ]
200 : : }
201 : :
202 [ # # ]: 0 : ScImportExport aObj( pDoc, aRange );
203 : 0 : aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
204 [ # # ]: 0 : if( aObj.IsRef() )
205 [ # # ][ # # ]: 0 : return aObj.ExportData( rMimeType, rData ) ? 1 : 0;
206 [ # # ][ + - ]: 5 : return 0;
207 : : }
208 : :
209 : 26 : void ScServerObject::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
210 : : {
211 : 26 : sal_Bool bDataChanged = false;
212 : :
213 : : // DocShell can't be tested via type info, because SFX_HINT_DYING comes from the dtor
214 [ - + ]: 26 : if ( &rBC == pDocSh )
215 : : {
216 : : // from DocShell, only SFX_HINT_DYING is interesting
217 [ # # ][ # # ]: 0 : if ( rHint.ISA(SfxSimpleHint) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING )
[ # # ]
218 : : {
219 : 0 : pDocSh = NULL;
220 : 0 : EndListening(*SFX_APP());
221 : : // don't access DocShell anymore for EndListening etc.
222 : : }
223 : : }
224 [ + - ]: 26 : else if (rBC.ISA(SfxApplication))
225 : : {
226 [ - + ]: 26 : if ( aItemStr.Len() && rHint.ISA(SfxSimpleHint) &&
[ # # # # ]
[ - + ]
227 : 0 : ((const SfxSimpleHint&)rHint).GetId() == SC_HINT_AREAS_CHANGED )
228 : : {
229 : : // check if named range was modified
230 : 0 : ScRange aNew;
231 [ # # ][ # # ]: 0 : if ( lcl_FillRangeFromName( aNew, pDocSh, aItemStr ) && aNew != aRange )
[ # # ][ # # ]
232 : 0 : bDataChanged = sal_True;
233 : : }
234 : : }
235 : : else
236 : : {
237 : : // must be from Area broadcasters
238 : :
239 [ # # ][ # # ]: 0 : const ScHint* pScHint = PTR_CAST( ScHint, &rHint );
240 [ # # ][ # # ]: 0 : if( pScHint && (pScHint->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING)) )
[ # # ]
241 : 0 : bDataChanged = sal_True;
242 [ # # ]: 0 : else if (rHint.ISA(ScAreaChangedHint)) // position of broadcaster changed
243 : : {
244 : 0 : ScRange aNewRange = ((const ScAreaChangedHint&)rHint).GetRange();
245 [ # # ]: 0 : if ( aRange != aNewRange )
246 : : {
247 : 0 : bRefreshListener = sal_True;
248 : 0 : bDataChanged = sal_True;
249 : : }
250 : : }
251 [ # # ]: 0 : else if (rHint.ISA(SfxSimpleHint))
252 : : {
253 : 0 : sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId();
254 [ # # ]: 0 : if (nId == SFX_HINT_DYING)
255 : : {
256 : : // If the range is being deleted, listening must be restarted
257 : : // after the deletion is complete (done in GetData)
258 : 0 : bRefreshListener = sal_True;
259 : 0 : bDataChanged = sal_True;
260 : : }
261 : : }
262 : : }
263 : :
264 [ - + ][ # # ]: 26 : if ( bDataChanged && HasDataLinks() )
[ - + ]
265 : 0 : SvLinkSource::NotifyDataChanged();
266 : 26 : }
267 : :
268 : :
269 : :
270 : :
271 : :
272 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|