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