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_forms.hxx"
30 
31 #include "FormattedField.hxx"
32 #include "services.hxx"
33 #include "property.hrc"
34 #include "property.hxx"
35 #include "frm_resource.hxx"
36 #include "frm_resource.hrc"
37 #include "propertybaghelper.hxx"
38 #include <comphelper/sequence.hxx>
39 #include <comphelper/numbers.hxx>
40 #include <connectivity/dbtools.hxx>
41 #include <connectivity/dbconversion.hxx>
42 #include <svl/zforlist.hxx>
43 #include <svl/numuno.hxx>
44 #include <vcl/svapp.hxx>
45 #include <tools/debug.hxx>
46 #include <tools/wintypes.hxx>
47 #include <i18npool/mslangid.hxx>
48 #include <rtl/textenc.h>
49 #include <com/sun/star/sdbc/DataType.hpp>
50 #include <com/sun/star/util/NumberFormat.hpp>
51 #include <com/sun/star/util/Date.hpp>
52 #include <com/sun/star/util/Time.hpp>
53 #include <com/sun/star/awt/MouseEvent.hpp>
54 #include <com/sun/star/form/XSubmit.hpp>
55 #include <com/sun/star/awt/XWindow.hpp>
56 #include <com/sun/star/awt/XKeyListener.hpp>
57 #include <com/sun/star/form/FormComponentType.hpp>
58 #include <com/sun/star/util/XNumberFormatsSupplier.hpp>
59 #include <com/sun/star/util/XNumberFormatTypes.hpp>
60 #include <com/sun/star/form/XForm.hpp>
61 #include <com/sun/star/container/XIndexAccess.hpp>
62 #include <vos/mutex.hxx>
63 	// needed as long as we use the SolarMutex
64 #include <comphelper/streamsection.hxx>
65 #include <cppuhelper/weakref.hxx>
66 #include <unotools/desktopterminationobserver.hxx>
67 
68 #include <list>
69 #include <algorithm>
70 
71 using namespace dbtools;
72 using namespace ::com::sun::star::uno;
73 using namespace ::com::sun::star::sdb;
74 using namespace ::com::sun::star::sdbc;
75 using namespace ::com::sun::star::sdbcx;
76 using namespace ::com::sun::star::beans;
77 using namespace ::com::sun::star::container;
78 using namespace ::com::sun::star::form;
79 using namespace ::com::sun::star::awt;
80 using namespace ::com::sun::star::io;
81 using namespace ::com::sun::star::lang;
82 using namespace ::com::sun::star::util;
83 using namespace ::com::sun::star::form::binding;
84 
85 namespace
86 {
87     typedef com::sun::star::util::Date UNODate;
88     typedef com::sun::star::util::Time UNOTime;
89     typedef com::sun::star::util::DateTime UNODateTime;
90 }
91 
92 //.........................................................................
93 namespace frm
94 {
95 
96 /*************************************************************************/
97 
98 class StandardFormatsSupplier : protected SvNumberFormatsSupplierObj, public ::utl::ITerminationListener
99 {
100 protected:
101             SvNumberFormatter*                       m_pMyPrivateFormatter;
102     static  WeakReference< XNumberFormatsSupplier >  s_xDefaultFormatsSupplier;
103 
104 public:
105     static Reference< XNumberFormatsSupplier > get( const Reference< XMultiServiceFactory >& _rxORB );
106 
107 	using SvNumberFormatsSupplierObj::operator new;
108 	using SvNumberFormatsSupplierObj::operator delete;
109 
110 protected:
111 	StandardFormatsSupplier(const Reference<XMultiServiceFactory>& _rxFactory,LanguageType _eSysLanguage);
112 	~StandardFormatsSupplier();
113 
114 protected:
115     virtual bool    queryTermination() const;
116     virtual void    notifyTermination();
117 };
118 
119 //------------------------------------------------------------------
120 WeakReference< XNumberFormatsSupplier > StandardFormatsSupplier::s_xDefaultFormatsSupplier;
121 
122 //------------------------------------------------------------------
123 StandardFormatsSupplier::StandardFormatsSupplier(const Reference< XMultiServiceFactory > & _rxFactory,LanguageType _eSysLanguage)
124 	:SvNumberFormatsSupplierObj()
125 	,m_pMyPrivateFormatter(new SvNumberFormatter(_rxFactory, _eSysLanguage))
126 {
127 	SetNumberFormatter(m_pMyPrivateFormatter);
128 
129     // #i29147# - 2004-06-18 - fs@openoffice.org
130     ::utl::DesktopTerminationObserver::registerTerminationListener( this );
131 }
132 
133 //------------------------------------------------------------------
134 StandardFormatsSupplier::~StandardFormatsSupplier()
135 {
136     ::utl::DesktopTerminationObserver::revokeTerminationListener( this );
137 
138     DELETEZ( m_pMyPrivateFormatter );
139 }
140 
141 //------------------------------------------------------------------
142 Reference< XNumberFormatsSupplier > StandardFormatsSupplier::get( const Reference< XMultiServiceFactory >& _rxORB )
143 {
144     LanguageType eSysLanguage = LANGUAGE_SYSTEM;
145     {
146         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
147         Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
148         if ( xSupplier.is() )
149             return xSupplier;
150 
151 	    // get the Office's locale
152 	    const Locale& rSysLocale = SvtSysLocale().GetLocaleData().getLocale();
153 	    // translate
154 	    eSysLanguage = MsLangId::convertLocaleToLanguage( rSysLocale );
155     }
156 
157     StandardFormatsSupplier* pSupplier = new StandardFormatsSupplier( _rxORB, eSysLanguage );
158     Reference< XNumberFormatsSupplier > xNewlyCreatedSupplier( pSupplier );
159 
160     {
161         ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
162         Reference< XNumberFormatsSupplier > xSupplier = s_xDefaultFormatsSupplier;
163         if ( xSupplier.is() )
164             // somebody used the small time frame where the mutex was not locked to create and set
165             // the supplier
166             return xSupplier;
167 
168         s_xDefaultFormatsSupplier = xNewlyCreatedSupplier;
169     }
170 
171     return xNewlyCreatedSupplier;
172 }
173 
174 //------------------------------------------------------------------
175 bool StandardFormatsSupplier::queryTermination() const
176 {
177     return true;
178 }
179 
180 //------------------------------------------------------------------
181 void StandardFormatsSupplier::notifyTermination()
182 {
183     Reference< XNumberFormatsSupplier > xKeepAlive = this;
184     // when the application is terminating, release our static reference so that we are cleared/destructed
185     // earlier than upon unloading the library
186     // #i29147# - 2004-06-18 - fs@openoffice.org
187     s_xDefaultFormatsSupplier = WeakReference< XNumberFormatsSupplier >( );
188 
189     SetNumberFormatter( NULL );
190     DELETEZ( m_pMyPrivateFormatter );
191 }
192 
193 /*************************************************************************/
194 //------------------------------------------------------------------
195 InterfaceRef SAL_CALL OFormattedControl_CreateInstance(const Reference<XMultiServiceFactory>& _rxFactory)
196 {
197 	return *(new OFormattedControl(_rxFactory));
198 }
199 
200 //------------------------------------------------------------------
201 Sequence<Type> OFormattedControl::_getTypes()
202 {
203 	return ::comphelper::concatSequences(
204 		OFormattedControl_BASE::getTypes(),
205 		OBoundControl::_getTypes()
206 	);
207 }
208 
209 //------------------------------------------------------------------
210 Any SAL_CALL OFormattedControl::queryAggregation(const Type& _rType) throw (RuntimeException)
211 {
212 	Any aReturn = OBoundControl::queryAggregation(_rType);
213 	if (!aReturn.hasValue())
214 		aReturn = OFormattedControl_BASE::queryInterface(_rType);
215 	return aReturn;
216 }
217 
218 
219 DBG_NAME(OFormattedControl);
220 //------------------------------------------------------------------------------
221 OFormattedControl::OFormattedControl(const Reference<XMultiServiceFactory>& _rxFactory)
222 			   :OBoundControl(_rxFactory, VCL_CONTROL_FORMATTEDFIELD)
223 			   ,m_nKeyEvent(0)
224 {
225 	DBG_CTOR(OFormattedControl,NULL);
226 
227 	increment(m_refCount);
228 	{
229 		Reference<XWindow>	xComp;
230 		if (query_aggregation(m_xAggregate, xComp))
231 		{
232 			xComp->addKeyListener(this);
233 		}
234 	}
235 	decrement(m_refCount);
236 }
237 
238 //------------------------------------------------------------------------------
239 OFormattedControl::~OFormattedControl()
240 {
241 	if( m_nKeyEvent )
242 		Application::RemoveUserEvent( m_nKeyEvent );
243 
244 	if (!OComponentHelper::rBHelper.bDisposed)
245 	{
246 		acquire();
247 		dispose();
248 	}
249 
250 	DBG_DTOR(OFormattedControl,NULL);
251 }
252 
253 // XKeyListener
254 //------------------------------------------------------------------------------
255 void OFormattedControl::disposing(const EventObject& _rSource) throw(RuntimeException)
256 {
257 	OBoundControl::disposing(_rSource);
258 }
259 
260 //------------------------------------------------------------------------------
261 void OFormattedControl::keyPressed(const ::com::sun::star::awt::KeyEvent& e) throw ( ::com::sun::star::uno::RuntimeException)
262 {
263 	if( e.KeyCode != KEY_RETURN || e.Modifiers != 0 )
264 		return;
265 
266 	// Steht das Control in einem Formular mit einer Submit-URL?
267 	Reference<com::sun::star::beans::XPropertySet>	xSet(getModel(), UNO_QUERY);
268 	if( !xSet.is() )
269 		return;
270 
271 	Reference<XFormComponent>  xFComp(xSet, UNO_QUERY);
272 	InterfaceRef  xParent = xFComp->getParent();
273 	if( !xParent.is() )
274 		return;
275 
276 	Reference<com::sun::star::beans::XPropertySet>	xFormSet(xParent, UNO_QUERY);
277 	if( !xFormSet.is() )
278 		return;
279 
280 	Any aTmp(xFormSet->getPropertyValue( PROPERTY_TARGET_URL ));
281 	if (!isA(aTmp, static_cast< ::rtl::OUString* >(NULL)) ||
282 		!getString(aTmp).getLength() )
283 		return;
284 
285 	Reference<XIndexAccess>  xElements(xParent, UNO_QUERY);
286 	sal_Int32 nCount = xElements->getCount();
287 	if( nCount > 1 )
288 	{
289 
290 		Reference<com::sun::star::beans::XPropertySet>	xFCSet;
291 		for( sal_Int32 nIndex=0; nIndex < nCount; nIndex++ )
292 		{
293 			//	Any aElement(xElements->getByIndex(nIndex));
294 			xElements->getByIndex(nIndex) >>= xFCSet;
295 
296 			if (hasProperty(PROPERTY_CLASSID, xFCSet) &&
297 				getINT16(xFCSet->getPropertyValue(PROPERTY_CLASSID)) == FormComponentType::TEXTFIELD)
298 			{
299 				// Noch ein weiteres Edit gefunden ==> dann nicht submitten
300 				if (xFCSet != xSet)
301 					return;
302 			}
303 		}
304 	}
305 
306 	// Da wir noch im Haender stehen, submit asynchron ausloesen
307 	if( m_nKeyEvent )
308 		Application::RemoveUserEvent( m_nKeyEvent );
309 	m_nKeyEvent = Application::PostUserEvent( LINK(this, OFormattedControl,
310 											OnKeyPressed) );
311 }
312 
313 //------------------------------------------------------------------------------
314 void OFormattedControl::keyReleased(const ::com::sun::star::awt::KeyEvent& /*e*/) throw ( ::com::sun::star::uno::RuntimeException)
315 {
316 }
317 
318 //------------------------------------------------------------------------------
319 IMPL_LINK(OFormattedControl, OnKeyPressed, void*, /*EMPTYARG*/)
320 {
321 	m_nKeyEvent = 0;
322 
323 	Reference<XFormComponent>  xFComp(getModel(), UNO_QUERY);
324 	InterfaceRef  xParent = xFComp->getParent();
325 	Reference<XSubmit>	xSubmit(xParent, UNO_QUERY);
326 	if (xSubmit.is())
327 		xSubmit->submit( Reference<XControl> (), ::com::sun::star::awt::MouseEvent() );
328 	return 0L;
329 }
330 
331 //------------------------------------------------------------------------------
332 StringSequence	OFormattedControl::getSupportedServiceNames() throw()
333 {
334 	StringSequence aSupported = OBoundControl::getSupportedServiceNames();
335 	aSupported.realloc(aSupported.getLength() + 1);
336 
337 	::rtl::OUString*pArray = aSupported.getArray();
338 	pArray[aSupported.getLength()-1] = FRM_SUN_CONTROL_FORMATTEDFIELD;
339 	return aSupported;
340 }
341 
342 //------------------------------------------------------------------------------
343 void OFormattedControl::setDesignMode(sal_Bool bOn) throw ( ::com::sun::star::uno::RuntimeException)
344 {
345 	OBoundControl::setDesignMode(bOn);
346 }
347 
348 /*************************************************************************/
349 DBG_NAME(OFormattedModel)
350 //------------------------------------------------------------------
351 void OFormattedModel::implConstruct()
352 {
353 	// members
354 	m_bOriginalNumeric = sal_False;
355 	m_bNumeric = sal_False;
356 	m_xOriginalFormatter = NULL;
357 	m_nKeyType = NumberFormat::UNDEFINED;
358 	m_aNullDate = DBTypeConversion::getStandardDate();
359 	m_nFieldType =  DataType::OTHER;
360 
361 	// default our formats supplier
362 	increment(m_refCount);
363 	setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
364 	decrement(m_refCount);
365 
366     startAggregatePropertyListening( PROPERTY_FORMATKEY );
367     startAggregatePropertyListening( PROPERTY_FORMATSSUPPLIER );
368 }
369 
370 //------------------------------------------------------------------
371 OFormattedModel::OFormattedModel(const Reference<XMultiServiceFactory>& _rxFactory)
372 	:OEditBaseModel(_rxFactory, VCL_CONTROLMODEL_FORMATTEDFIELD, FRM_SUN_CONTROL_FORMATTEDFIELD, sal_True, sal_True )
373 							// use the old control name for compytibility reasons
374 	,OErrorBroadcaster( OComponentHelper::rBHelper )
375 {
376 	DBG_CTOR(OFormattedModel, NULL);
377 
378 	implConstruct();
379 
380 	m_nClassId = FormComponentType::TEXTFIELD;
381     initValueProperty( PROPERTY_EFFECTIVE_VALUE, PROPERTY_ID_EFFECTIVE_VALUE );
382 }
383 
384 //------------------------------------------------------------------
385 OFormattedModel::OFormattedModel( const OFormattedModel* _pOriginal, const Reference< XMultiServiceFactory >& _rxFactory )
386 	:OEditBaseModel( _pOriginal, _rxFactory )
387 	,OErrorBroadcaster( OComponentHelper::rBHelper )
388 {
389 	DBG_CTOR(OFormattedModel, NULL);
390 
391 	implConstruct();
392 }
393 
394 //------------------------------------------------------------------------------
395 OFormattedModel::~OFormattedModel()
396 {
397 	DBG_DTOR(OFormattedModel, NULL);
398 }
399 
400 // XCloneable
401 //------------------------------------------------------------------------------
402 IMPLEMENT_DEFAULT_CLONING( OFormattedModel )
403 
404 //------------------------------------------------------------------------------
405 void SAL_CALL OFormattedModel::disposing()
406 {
407 	OErrorBroadcaster::disposing();
408 	OEditBaseModel::disposing();
409 }
410 
411 // XServiceInfo
412 //------------------------------------------------------------------------------
413 StringSequence OFormattedModel::getSupportedServiceNames() throw()
414 {
415 	StringSequence aSupported = OEditBaseModel::getSupportedServiceNames();
416 
417     sal_Int32 nOldLen = aSupported.getLength();
418 	aSupported.realloc( nOldLen + 8 );
419 	::rtl::OUString* pStoreTo = aSupported.getArray() + nOldLen;
420 
421     *pStoreTo++ = BINDABLE_CONTROL_MODEL;
422     *pStoreTo++ = DATA_AWARE_CONTROL_MODEL;
423     *pStoreTo++ = VALIDATABLE_CONTROL_MODEL;
424 
425     *pStoreTo++ = BINDABLE_DATA_AWARE_CONTROL_MODEL;
426     *pStoreTo++ = VALIDATABLE_BINDABLE_CONTROL_MODEL;
427 
428     *pStoreTo++ = FRM_SUN_COMPONENT_FORMATTEDFIELD;
429     *pStoreTo++ = FRM_SUN_COMPONENT_DATABASE_FORMATTEDFIELD;
430     *pStoreTo++ = BINDABLE_DATABASE_FORMATTED_FIELD;
431 
432     return aSupported;
433 }
434 
435 // XAggregation
436 //------------------------------------------------------------------------------
437 Any SAL_CALL OFormattedModel::queryAggregation(const Type& _rType) throw(RuntimeException)
438 {
439 	Any aReturn = OEditBaseModel::queryAggregation( _rType );
440 	return aReturn.hasValue() ? aReturn : OErrorBroadcaster::queryInterface( _rType );
441 }
442 
443 // XTypeProvider
444 //------------------------------------------------------------------------------
445 Sequence< Type > OFormattedModel::_getTypes()
446 {
447 	return ::comphelper::concatSequences(
448 		OEditBaseModel::_getTypes(),
449 		OErrorBroadcaster::getTypes()
450 	);
451 }
452 
453 // XPersistObject
454 //------------------------------------------------------------------------------
455 ::rtl::OUString SAL_CALL OFormattedModel::getServiceName() throw ( ::com::sun::star::uno::RuntimeException)
456 {
457 	return ::rtl::OUString(FRM_COMPONENT_EDIT);
458 }
459 
460 // XPropertySet
461 //------------------------------------------------------------------------------
462 void OFormattedModel::describeFixedProperties( Sequence< Property >& _rProps ) const
463 {
464 	BEGIN_DESCRIBE_PROPERTIES( 3, OEditBaseModel )
465 		DECL_BOOL_PROP1(EMPTY_IS_NULL,							BOUND);
466 		DECL_PROP1(TABINDEX,			sal_Int16,				BOUND);
467 		DECL_BOOL_PROP2(FILTERPROPOSAL, 						BOUND, MAYBEDEFAULT);
468 	END_DESCRIBE_PROPERTIES();
469 }
470 
471 //------------------------------------------------------------------------------
472 void OFormattedModel::describeAggregateProperties( Sequence< Property >& _rAggregateProps ) const
473 {
474     OEditBaseModel::describeAggregateProperties( _rAggregateProps );
475 
476 	// TreatAsNumeric nicht transient : wir wollen es an der UI anbinden (ist noetig, um dem EffectiveDefault
477 	// - der kann Text oder Zahl sein - einen Sinn zu geben)
478 	ModifyPropertyAttributes(_rAggregateProps, PROPERTY_TREATASNUMERIC, 0, PropertyAttribute::TRANSIENT);
479 	// same for FormatKey
480 	// (though the paragraph above for the TreatAsNumeric does not hold anymore - we do not have an UI for this.
481 	// But we have for the format key ...)
482 	// 25.06.2001 - 87862 - frank.schoenheit@sun.com
483 	ModifyPropertyAttributes(_rAggregateProps, PROPERTY_FORMATKEY, 0, PropertyAttribute::TRANSIENT);
484 
485 	RemoveProperty(_rAggregateProps, PROPERTY_STRICTFORMAT);
486 		// no strict format property for formatted fields: it does not make sense, 'cause
487 		// there is no general way to decide which characters/sub strings are allowed during the input of an
488 		// arbitraryly formatted control
489 		// 81441 - 12/07/00 - FS
490 }
491 
492 //------------------------------------------------------------------------------
493 void OFormattedModel::getFastPropertyValue(Any& rValue, sal_Int32 nHandle) const
494 {
495 	OEditBaseModel::getFastPropertyValue(rValue, nHandle);
496 }
497 
498 //------------------------------------------------------------------------------
499 void OFormattedModel::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const Any& rValue) throw ( ::com::sun::star::uno::Exception)
500 {
501 	OEditBaseModel::setFastPropertyValue_NoBroadcast(nHandle, rValue);
502 }
503 
504 //------------------------------------------------------------------------------
505 sal_Bool OFormattedModel::convertFastPropertyValue(Any& rConvertedValue, Any& rOldValue, sal_Int32 nHandle, const Any& rValue)
506 														throw( IllegalArgumentException )
507 {
508 	return OEditBaseModel::convertFastPropertyValue(rConvertedValue, rOldValue, nHandle, rValue);
509 }
510 
511 //------------------------------------------------------------------------------
512 void OFormattedModel::setPropertyToDefaultByHandle(sal_Int32 nHandle)
513 {
514 	if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
515 	{
516 		Reference<XNumberFormatsSupplier>  xSupplier = calcDefaultFormatsSupplier();
517 		DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::setPropertyToDefaultByHandle(FORMATSSUPPLIER) : have no aggregate !");
518 		if (m_xAggregateSet.is())
519 			m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
520 	}
521 	else
522 		OEditBaseModel::setPropertyToDefaultByHandle(nHandle);
523 }
524 
525 //------------------------------------------------------------------------------
526 void OFormattedModel::setPropertyToDefault(const ::rtl::OUString& aPropertyName) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
527 {
528 	OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
529 	sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
530 
531 	if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
532 		setPropertyToDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
533 	else
534 		OEditBaseModel::setPropertyToDefault(aPropertyName);
535 }
536 
537 //------------------------------------------------------------------------------
538 Any OFormattedModel::getPropertyDefaultByHandle( sal_Int32 nHandle ) const
539 {
540 	if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
541 	{
542 		Reference<XNumberFormatsSupplier>  xSupplier = calcDefaultFormatsSupplier();
543 		return makeAny(xSupplier);
544 	}
545 	else
546 		return OEditBaseModel::getPropertyDefaultByHandle(nHandle);
547 }
548 
549 //------------------------------------------------------------------------------
550 Any SAL_CALL OFormattedModel::getPropertyDefault( const ::rtl::OUString& aPropertyName ) throw( com::sun::star::beans::UnknownPropertyException, RuntimeException )
551 {
552 	OPropertyArrayAggregationHelper& rPH = m_aPropertyBagHelper.getInfoHelper();
553 	sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
554 
555 	if (nHandle == PROPERTY_ID_FORMATSSUPPLIER)
556 		return getPropertyDefaultByHandle(PROPERTY_ID_FORMATSSUPPLIER);
557 	else
558 		return OEditBaseModel::getPropertyDefault(aPropertyName);
559 }
560 
561 //------------------------------------------------------------------------------
562 void OFormattedModel::_propertyChanged( const com::sun::star::beans::PropertyChangeEvent& evt ) throw(RuntimeException)
563 {
564     // TODO: check how this works with external bindings
565 
566     OSL_ENSURE( evt.Source == m_xAggregateSet, "OFormattedModel::_propertyChanged: where did this come from?" );
567 	if ( evt.Source == m_xAggregateSet )
568 	{
569         Reference< XPropertySet > xSourceSet( evt.Source, UNO_QUERY );
570 		if ( evt.PropertyName.equals( PROPERTY_FORMATKEY ) )
571 		{
572 			if ( evt.NewValue.getValueType().getTypeClass() == TypeClass_LONG )
573 			{
574 				try
575 				{
576                     ::osl::MutexGuard aGuard( m_aMutex );
577 
578 					Reference<XNumberFormatsSupplier> xSupplier( calcFormatsSupplier() );
579 					m_nKeyType	= getNumberFormatType(xSupplier->getNumberFormats(), getINT32( evt.NewValue ) );
580 
581                     // as m_aSaveValue (which is used by commitControlValueToDbColumn) is format dependent we have
582 					// to recalc it, which is done by translateDbColumnToControlValue
583 					if ( m_xColumn.is() && m_xAggregateFastSet.is()  && !m_xCursor->isBeforeFirst() && !m_xCursor->isAfterLast())
584 					{
585 						setControlValue( translateDbColumnToControlValue(), eOther );
586 					}
587 
588                     // if we're connected to an external value binding, then re-calculate the type
589                     // used to exchange the value - it depends on the format, too
590                     if ( hasExternalValueBinding() )
591                     {
592                         calculateExternalValueType();
593                     }
594 				}
595 				catch(Exception&)
596 				{
597 				}
598 			}
599             return;
600 		}
601 
602         if ( evt.PropertyName.equals( PROPERTY_FORMATSSUPPLIER ) )
603 		{
604             updateFormatterNullDate();
605             return;
606         }
607 
608         OBoundControlModel::_propertyChanged( evt );
609 	}
610 }
611 
612 //------------------------------------------------------------------------------
613 void OFormattedModel::updateFormatterNullDate()
614 {
615     // calc the current NULL date
616     Reference< XNumberFormatsSupplier > xSupplier( calcFormatsSupplier() );
617     if ( xSupplier.is() )
618         xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NullDate" ) ) ) >>= m_aNullDate;
619 }
620 
621 //------------------------------------------------------------------------------
622 Reference< XNumberFormatsSupplier > OFormattedModel::calcFormatsSupplier() const
623 {
624 	Reference<XNumberFormatsSupplier>  xSupplier;
625 
626 	DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::calcFormatsSupplier : have no aggregate !");
627 	// hat mein aggregiertes Model einen FormatSupplier ?
628 	if( m_xAggregateSet.is() )
629 		m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER) >>= xSupplier;
630 
631     if (!xSupplier.is())
632 		// check if my parent form has a supplier
633 		xSupplier = calcFormFormatsSupplier();
634 
635 	if (!xSupplier.is())
636 		xSupplier = calcDefaultFormatsSupplier();
637 
638 	DBG_ASSERT(xSupplier.is(), "OFormattedModel::calcFormatsSupplier : no supplier !");
639 		// jetzt sollte aber einer da sein
640 	return xSupplier;
641 }
642 
643 //------------------------------------------------------------------------------
644 Reference<XNumberFormatsSupplier>  OFormattedModel::calcFormFormatsSupplier() const
645 {
646 	Reference<XChild>  xMe;
647 	query_interface(static_cast<XWeak*>(const_cast<OFormattedModel*>(this)), xMe);
648 	// damit stellen wir sicher, dass wir auch fuer den Fall der Aggregation das richtige
649 	// Objekt bekommen
650 	DBG_ASSERT(xMe.is(), "OFormattedModel::calcFormFormatsSupplier : I should have a content interface !");
651 
652 	// jetzt durchhangeln nach oben, bis wir auf eine starform treffen (angefangen mit meinem eigenen Parent)
653 	Reference<XChild>  xParent(xMe->getParent(), UNO_QUERY);
654 	Reference<XForm>  xNextParentForm(xParent, UNO_QUERY);
655 	while (!xNextParentForm.is() && xParent.is())
656 	{
657 		xParent 		= xParent.query( xParent->getParent() );
658 		xNextParentForm = xNextParentForm.query( xParent );
659 	}
660 
661 	if (!xNextParentForm.is())
662 	{
663 		DBG_ERROR("OFormattedModel::calcFormFormatsSupplier : have no ancestor which is a form !");
664 		return NULL;
665 	}
666 
667 	// den FormatSupplier von meinem Vorfahren (falls der einen hat)
668 	Reference< XRowSet > xRowSet( xNextParentForm, UNO_QUERY );
669 	Reference< XNumberFormatsSupplier > xSupplier;
670 	if (xRowSet.is())
671 		xSupplier = getNumberFormats( getConnection(xRowSet), sal_True, getContext().getLegacyServiceFactory() );
672 	return xSupplier;
673 }
674 
675 //------------------------------------------------------------------------------
676 Reference< XNumberFormatsSupplier > OFormattedModel::calcDefaultFormatsSupplier() const
677 {
678     return StandardFormatsSupplier::get( getContext().getLegacyServiceFactory() );
679 }
680 
681 // XBoundComponent
682 //------------------------------------------------------------------------------
683 void OFormattedModel::loaded(const EventObject& rEvent) throw ( ::com::sun::star::uno::RuntimeException)
684 {
685 	// HACK : our onConnectedDbColumn accesses our NumberFormatter which locks the solar mutex (as it doesn't have
686 	// an own one). To prevent deadlocks with other threads which may request a property from us in an
687 	// UI-triggered action (e.g. an tooltip) we lock the solar mutex _here_ before our base class locks
688 	// it's own muext (which is used for property requests)
689 	// alternative a): we use two mutexes, one which is passed to the OPropertysetHelper and used for
690 	// property requests and one for our own code. This would need a lot of code rewriting
691 	// alternative b): The NumberFormatter has to be really threadsafe (with an own mutex), which is
692 	// the only "clean" solution for me.
693 	// FS - 69603 - 02.11.99
694 
695 	::vos::OGuard aGuard(Application::GetSolarMutex());
696 	OEditBaseModel::loaded(rEvent);
697 }
698 
699 //------------------------------------------------------------------------------
700 void OFormattedModel::onConnectedDbColumn( const Reference< XInterface >& _rxForm )
701 {
702 	m_xOriginalFormatter = NULL;
703 
704 	// get some properties of the field
705 	m_nFieldType = DataType::OTHER;
706 	Reference<XPropertySet> xField = getField();
707 	if ( xField.is() )
708 		xField->getPropertyValue( PROPERTY_FIELDTYPE ) >>= m_nFieldType;
709 
710     sal_Int32 nFormatKey = 0;
711 
712 	DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::onConnectedDbColumn : have no aggregate !");
713 	if (m_xAggregateSet.is())
714 	{	// all the following doesn't make any sense if we have no aggregate ...
715 		Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
716 		DBG_ASSERT( aSupplier.hasValue(), "OFormattedModel::onConnectedDbColumn : invalid property value !" );
717 		// das sollte im Constructor oder im read auf was richtiges gesetzt worden sein
718 
719 		Any aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
720         if ( !(aFmtKey >>= nFormatKey ) )
721 		{	// nobody gave us a format to use. So we examine the field we're bound to for a
722             // format key, and use it ourself, too
723 			sal_Int32 nType = DataType::VARCHAR;
724 			if (xField.is())
725 			{
726 				aFmtKey = xField->getPropertyValue(PROPERTY_FORMATKEY);
727 				xField->getPropertyValue(PROPERTY_FIELDTYPE) >>= nType ;
728 			}
729 
730 			Reference<XNumberFormatsSupplier>  xSupplier = calcFormFormatsSupplier();
731 			DBG_ASSERT(xSupplier.is(), "OFormattedModel::onConnectedDbColumn : bound to a field but no parent with a formatter ? how this ?");
732 			if (xSupplier.is())
733 			{
734 				m_bOriginalNumeric = getBOOL(getPropertyValue(PROPERTY_TREATASNUMERIC));
735 
736 				if (!aFmtKey.hasValue())
737 				{	// we aren't bound to a field (or this field's format is invalid)
738 					// -> determine the standard text (or numeric) format of the supplier
739 					Reference<XNumberFormatTypes>  xTypes(xSupplier->getNumberFormats(), UNO_QUERY);
740 					if (xTypes.is())
741 					{
742 						Locale aApplicationLocale = Application::GetSettings().GetUILocale();
743 
744 						if (m_bOriginalNumeric)
745 							aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::NUMBER, aApplicationLocale);
746 						else
747 							aFmtKey <<= (sal_Int32)xTypes->getStandardFormat(NumberFormat::TEXT, aApplicationLocale);
748 					}
749 				}
750 
751 				aSupplier >>= m_xOriginalFormatter;
752 				m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
753 				m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, aFmtKey);
754 
755 				// das Numeric-Flag an mein gebundenes Feld anpassen
756 				if (xField.is())
757 				{
758 					m_bNumeric = sal_False;
759 					switch (nType)
760 					{
761 						case DataType::BIT:
762 						case DataType::BOOLEAN:
763 						case DataType::TINYINT:
764 						case DataType::SMALLINT:
765 						case DataType::INTEGER:
766 						case DataType::BIGINT:
767 						case DataType::FLOAT:
768 						case DataType::REAL:
769 						case DataType::DOUBLE:
770 						case DataType::NUMERIC:
771 						case DataType::DECIMAL:
772 						case DataType::DATE:
773 						case DataType::TIME:
774 						case DataType::TIMESTAMP:
775 							m_bNumeric = sal_True;
776 							break;
777 					}
778 				}
779 				else
780 					m_bNumeric = m_bOriginalNumeric;
781 
782 				setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bNumeric));
783 
784                 OSL_VERIFY( aFmtKey >>= nFormatKey );
785 			}
786 		}
787 	}
788 
789 	Reference<XNumberFormatsSupplier>  xSupplier = calcFormatsSupplier();
790 	m_bNumeric = getBOOL( getPropertyValue( PROPERTY_TREATASNUMERIC ) );
791 	m_nKeyType	= getNumberFormatType( xSupplier->getNumberFormats(), nFormatKey );
792 	xSupplier->getNumberFormatSettings()->getPropertyValue( ::rtl::OUString::createFromAscii("NullDate") ) >>= m_aNullDate;
793 
794 	OEditBaseModel::onConnectedDbColumn( _rxForm );
795 }
796 
797 //------------------------------------------------------------------------------
798 void OFormattedModel::onDisconnectedDbColumn()
799 {
800 	OEditBaseModel::onDisconnectedDbColumn();
801 	if (m_xOriginalFormatter.is())
802 	{	// unser aggregiertes Model hatte keinerlei Format-Informationen
803 		m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(m_xOriginalFormatter));
804 		m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, Any());
805 		setPropertyValue(PROPERTY_TREATASNUMERIC, makeAny((sal_Bool)m_bOriginalNumeric));
806 		m_xOriginalFormatter = NULL;
807 	}
808 
809 	m_nFieldType = DataType::OTHER;
810 	m_nKeyType	 = NumberFormat::UNDEFINED;
811 	m_aNullDate  = DBTypeConversion::getStandardDate();
812 }
813 
814 //------------------------------------------------------------------------------
815 void OFormattedModel::write(const Reference<XObjectOutputStream>& _rxOutStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
816 {
817 	OEditBaseModel::write(_rxOutStream);
818 	_rxOutStream->writeShort(0x0003);
819 
820 	DBG_ASSERT(m_xAggregateSet.is(), "OFormattedModel::write : have no aggregate !");
821 
822 	// mein Format (evtl. void) in ein persistentes Format bringen (der Supplier zusammen mit dem Key ist es zwar auch,
823 	// aber deswegen muessen wir ja nicht gleich den ganzen Supplier speichern, das waere ein klein wenig Overhead ;)
824 
825 		Reference<XNumberFormatsSupplier>  xSupplier;
826 		Any aFmtKey;
827 	sal_Bool bVoidKey = sal_True;
828 	if (m_xAggregateSet.is())
829 	{
830 		Any aSupplier = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATSSUPPLIER);
831         if (aSupplier.getValueType().getTypeClass() != TypeClass_VOID)
832 		{
833             OSL_VERIFY( aSupplier >>= xSupplier );
834 		}
835 
836 		aFmtKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
837 		bVoidKey = (!xSupplier.is() || !aFmtKey.hasValue()) || (isLoaded() && m_xOriginalFormatter.is());
838 			// (kein Fomatter und/oder Key) oder (loaded und faked Formatter)
839 	}
840 
841 	_rxOutStream->writeBoolean(!bVoidKey);
842 	if (!bVoidKey)
843 	{
844 		// aus dem FormatKey und dem Formatter persistente Angaben basteln
845 
846 		Any aKey = m_xAggregateSet->getPropertyValue(PROPERTY_FORMATKEY);
847 		sal_Int32 nKey = aKey.hasValue() ? getINT32(aKey) : 0;
848 
849 		Reference<XNumberFormats>  xFormats = xSupplier->getNumberFormats();
850 
851 		::rtl::OUString 		sFormatDescription;
852 		LanguageType	eFormatLanguage = LANGUAGE_DONTKNOW;
853 
854 		static const ::rtl::OUString s_aLocaleProp = ::rtl::OUString::createFromAscii("Locale");
855 		Reference<com::sun::star::beans::XPropertySet>	xFormat = xFormats->getByKey(nKey);
856 		if (hasProperty(s_aLocaleProp, xFormat))
857 		{
858 			Any aLocale = xFormat->getPropertyValue(s_aLocaleProp);
859 			DBG_ASSERT(isA(aLocale, static_cast<Locale*>(NULL)), "OFormattedModel::write : invalid language property !");
860 			if (isA(aLocale, static_cast<Locale*>(NULL)))
861 			{
862 				Locale* pLocale = (Locale*)aLocale.getValue();
863 				eFormatLanguage = MsLangId::convertLocaleToLanguage( *pLocale );
864 			}
865 		}
866 
867 		static const ::rtl::OUString s_aFormatStringProp = ::rtl::OUString::createFromAscii("FormatString");
868 		if (hasProperty(s_aFormatStringProp, xFormat))
869 			xFormat->getPropertyValue(s_aFormatStringProp) >>= sFormatDescription;
870 
871 		_rxOutStream->writeUTF(sFormatDescription);
872 		_rxOutStream->writeLong((sal_Int32)eFormatLanguage);
873 	}
874 
875 	// version 2 : write the properties common to all OEditBaseModels
876 	writeCommonEditProperties(_rxOutStream);
877 
878 	// version 3 : write the effective value property of the aggregate
879 	// Due to a bug within the UnoControlFormattedFieldModel implementation (our default aggregate) this props value isn't correctly read
880 	// and this can't be corrected without being incompatible.
881 	// so we have our own handling.
882 
883 	// and to be a little bit more compatible we make the following section skippable
884 	{
885 		Reference< XDataOutputStream > xOut(_rxOutStream, UNO_QUERY);
886 		OStreamSection aDownCompat(xOut);
887 
888 		// a sub version within the skippable block
889 		_rxOutStream->writeShort(0x0000);
890 
891 		// version 0: the effective value of the aggregate
892 				Any aEffectiveValue;
893 		if (m_xAggregateSet.is())
894 		{
895 			try { aEffectiveValue = m_xAggregateSet->getPropertyValue(PROPERTY_EFFECTIVE_VALUE); } catch(Exception&) { }
896 		}
897 
898 		{
899 			OStreamSection aDownCompat2(xOut);
900 			switch (aEffectiveValue.getValueType().getTypeClass())
901 			{
902 				case TypeClass_STRING:
903 					_rxOutStream->writeShort(0x0000);
904 					_rxOutStream->writeUTF(::comphelper::getString(aEffectiveValue));
905 					break;
906 				case TypeClass_DOUBLE:
907 					_rxOutStream->writeShort(0x0001);
908 					_rxOutStream->writeDouble(::comphelper::getDouble(aEffectiveValue));
909 					break;
910 				default:	// void and all unknown states
911 					DBG_ASSERT(!aEffectiveValue.hasValue(), "FmXFormattedModel::write : unknown property value type !");
912 					_rxOutStream->writeShort(0x0002);
913 					break;
914 			}
915 		}
916 	}
917 }
918 
919 //------------------------------------------------------------------------------
920 void OFormattedModel::read(const Reference<XObjectInputStream>& _rxInStream) throw ( ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException)
921 {
922 	OEditBaseModel::read(_rxInStream);
923 	sal_uInt16 nVersion = _rxInStream->readShort();
924 
925 	Reference<XNumberFormatsSupplier>  xSupplier;
926 	sal_Int32 nKey = -1;
927 	switch (nVersion)
928 	{
929 		case 0x0001 :
930 		case 0x0002 :
931 		case 0x0003 :
932 		{
933 			sal_Bool bNonVoidKey = _rxInStream->readBoolean();
934 			if (bNonVoidKey)
935 			{
936 				// den String und die Language lesen ....
937 				::rtl::OUString sFormatDescription = _rxInStream->readUTF();
938 				LanguageType eDescriptionLanguage = (LanguageType)_rxInStream->readLong();
939 
940 				// und daraus von einem Formatter zu einem Key zusammenwuerfeln lassen ...
941 				xSupplier = calcFormatsSupplier();
942 					// calcFormatsSupplier nimmt erst den vom Model, dann einen von der starform, dann einen ganz neuen ....
943 				Reference<XNumberFormats>  xFormats = xSupplier->getNumberFormats();
944 
945 				if (xFormats.is())
946 				{
947 					Locale aDescriptionLanguage( MsLangId::convertLanguageToLocale(eDescriptionLanguage));
948 
949 					nKey = xFormats->queryKey(sFormatDescription, aDescriptionLanguage, sal_False);
950 					if (nKey == (sal_Int32)-1)
951 					{	// noch nicht vorhanden in meinem Formatter ...
952 						nKey = xFormats->addNew(sFormatDescription, aDescriptionLanguage);
953 					}
954 				}
955 			}
956 			if ((nVersion == 0x0002) || (nVersion == 0x0003))
957 				readCommonEditProperties(_rxInStream);
958 
959 			if (nVersion == 0x0003)
960 			{	// since version 3 there is a "skippable" block at this position
961 				Reference< XDataInputStream > xIn(_rxInStream, UNO_QUERY);
962 				OStreamSection aDownCompat(xIn);
963 
964 				sal_Int16 nSubVersion = _rxInStream->readShort();
965                 (void)nSubVersion;
966 
967 				// version 0 and higher : the "effective value" property
968                 Any aEffectiveValue;
969 				{
970 					OStreamSection aDownCompat2(xIn);
971 					switch (_rxInStream->readShort())
972 					{
973 						case 0: // String
974 							aEffectiveValue <<= _rxInStream->readUTF();
975 							break;
976 						case 1: // double
977 							aEffectiveValue <<= (double)_rxInStream->readDouble();
978 							break;
979 						case 2:
980 							break;
981 						case 3:
982 							DBG_ERROR("FmXFormattedModel::read : unknown effective value type !");
983 					}
984 				}
985 
986 				// this property is only to be set if we have no control source : in all other cases the base class did a
987 				// reset after it's read and this set the effective value to a default value
988 				if ( m_xAggregateSet.is() && ( getControlSource().getLength() == 0 ) )
989 				{
990 					try
991 					{
992 						m_xAggregateSet->setPropertyValue(PROPERTY_EFFECTIVE_VALUE, aEffectiveValue);
993 					}
994 					catch(Exception&)
995 					{
996 					}
997 				}
998 			}
999 		}
1000 		break;
1001 		default :
1002 			DBG_ERROR("OFormattedModel::read : unknown version !");
1003 			// dann bleibt das Format des aggregierten Sets, wie es bei der Erzeugung ist : void
1004 			defaultCommonEditProperties();
1005 			break;
1006 	}
1007 
1008 	if ((nKey != -1) && m_xAggregateSet.is())
1009 	{
1010 				m_xAggregateSet->setPropertyValue(PROPERTY_FORMATSSUPPLIER, makeAny(xSupplier));
1011 				m_xAggregateSet->setPropertyValue(PROPERTY_FORMATKEY, makeAny((sal_Int32)nKey));
1012 	}
1013 	else
1014 	{
1015 		setPropertyToDefault(PROPERTY_FORMATSSUPPLIER);
1016 		setPropertyToDefault(PROPERTY_FORMATKEY);
1017 	}
1018 }
1019 
1020 //------------------------------------------------------------------------------
1021 sal_uInt16 OFormattedModel::getPersistenceFlags() const
1022 {
1023 	return (OEditBaseModel::getPersistenceFlags() & ~PF_HANDLE_COMMON_PROPS);
1024 	// a) we do our own call to writeCommonEditProperties
1025 }
1026 
1027 //------------------------------------------------------------------------------
1028 sal_Bool OFormattedModel::commitControlValueToDbColumn( bool /*_bPostReset*/ )
1029 {
1030 	Any aControlValue( m_xAggregateFastSet->getFastPropertyValue( getValuePropertyAggHandle() ) );
1031 	if ( aControlValue != m_aSaveValue )
1032 	{
1033 		// Leerstring + EmptyIsNull = void
1034 		if	(	!aControlValue.hasValue()
1035 			||	(	( aControlValue.getValueType().getTypeClass() == TypeClass_STRING )
1036 				&&	( getString( aControlValue ).getLength() == 0 )
1037 				&&	m_bEmptyIsNull
1038 				)
1039 			)
1040 			m_xColumnUpdate->updateNull();
1041 		else
1042 		{
1043 			try
1044 			{
1045                 double f = 0.0;
1046 				if ( aControlValue.getValueType().getTypeClass() == TypeClass_DOUBLE || (aControlValue >>= f)) // #i110323
1047 				{
1048 					DBTypeConversion::setValue( m_xColumnUpdate, m_aNullDate, getDouble( aControlValue ), m_nKeyType );
1049 				}
1050 				else
1051 				{
1052 					DBG_ASSERT( aControlValue.getValueType().getTypeClass() == TypeClass_STRING, "OFormattedModel::commitControlValueToDbColumn: invalud value type !" );
1053 					m_xColumnUpdate->updateString( getString( aControlValue ) );
1054 				}
1055 			}
1056 			catch(Exception&)
1057 			{
1058 				return sal_False;
1059 			}
1060 		}
1061 		m_aSaveValue = aControlValue;
1062 	}
1063 	return sal_True;
1064 }
1065 
1066 //------------------------------------------------------------------------------
1067 void OFormattedModel::onConnectedExternalValue( )
1068 {
1069     OEditBaseModel::onConnectedExternalValue();
1070     updateFormatterNullDate();
1071 }
1072 
1073 //------------------------------------------------------------------------------
1074 Any OFormattedModel::translateExternalValueToControlValue( const Any& _rExternalValue ) const
1075 {
1076     Any aControlValue;
1077     switch( _rExternalValue.getValueTypeClass() )
1078     {
1079     case TypeClass_VOID:
1080         break;
1081 
1082     case TypeClass_STRING:
1083         aControlValue = _rExternalValue;
1084         break;
1085 
1086     case TypeClass_BOOLEAN:
1087     {
1088         sal_Bool bExternalValue = sal_False;
1089         _rExternalValue >>= bExternalValue;
1090         aControlValue <<= (double)( bExternalValue ? 1 : 0 );
1091     }
1092     break;
1093 
1094     default:
1095     {
1096         if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1097         {
1098             UNODate aDate;
1099             _rExternalValue >>= aDate;
1100             aControlValue <<= DBTypeConversion::toDouble( aDate, m_aNullDate );
1101         }
1102         else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1103         {
1104             UNOTime aTime;
1105             _rExternalValue >>= aTime;
1106             aControlValue <<= DBTypeConversion::toDouble( aTime );
1107         }
1108         else if ( _rExternalValue.getValueType().equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1109         {
1110             UNODateTime aDateTime;
1111             _rExternalValue >>= aDateTime;
1112             aControlValue <<= DBTypeConversion::toDouble( aDateTime, m_aNullDate );
1113         }
1114         else
1115         {
1116             OSL_ENSURE( _rExternalValue.getValueTypeClass() == TypeClass_DOUBLE,
1117                 "OFormattedModel::translateExternalValueToControlValue: don't know how to translate this type!" );
1118             double fValue = 0;
1119             OSL_VERIFY( _rExternalValue >>= fValue );
1120             aControlValue <<= fValue;
1121         }
1122     }
1123     }
1124 
1125     return aControlValue;
1126 }
1127 
1128 //------------------------------------------------------------------------------
1129 Any OFormattedModel::translateControlValueToExternalValue( ) const
1130 {
1131     OSL_PRECOND( hasExternalValueBinding(),
1132         "OFormattedModel::translateControlValueToExternalValue: precondition not met!" );
1133 
1134     Any aControlValue( getControlValue() );
1135     if ( !aControlValue.hasValue() )
1136         return aControlValue;
1137 
1138     Any aExternalValue;
1139 
1140     // translate into the the external value type
1141     Type aExternalValueType( getExternalValueType() );
1142     switch ( aExternalValueType.getTypeClass() )
1143     {
1144     case TypeClass_STRING:
1145     {
1146         ::rtl::OUString sString;
1147         if ( aControlValue >>= sString )
1148         {
1149             aExternalValue <<= sString;
1150             break;
1151         }
1152     }
1153     // NO break here!
1154 
1155     case TypeClass_BOOLEAN:
1156     {
1157         double fValue = 0;
1158         OSL_VERIFY( aControlValue >>= fValue );
1159             // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1160             // and the control value is a string. This implies some weird misconfiguration
1161             // of the FormattedModel, so we won't care for it for the moment.
1162         aExternalValue <<= (sal_Bool)( fValue ? sal_True : sal_False );
1163     }
1164     break;
1165 
1166     default:
1167     {
1168         double fValue = 0;
1169         OSL_VERIFY( aControlValue >>= fValue );
1170             // if this asserts ... well, the somebody set the TreatAsNumeric property to false,
1171             // and the control value is a string. This implies some weird misconfiguration
1172             // of the FormattedModel, so we won't care for it for the moment.
1173 
1174         if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODate* >( NULL ) ) ) )
1175         {
1176             aExternalValue <<= DBTypeConversion::toDate( fValue, m_aNullDate );
1177         }
1178         else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNOTime* >( NULL ) ) ) )
1179         {
1180             aExternalValue <<= DBTypeConversion::toTime( fValue );
1181         }
1182         else if ( aExternalValueType.equals( ::getCppuType( static_cast< UNODateTime* >( NULL ) ) ) )
1183         {
1184             aExternalValue <<= DBTypeConversion::toDateTime( fValue, m_aNullDate );
1185         }
1186         else
1187         {
1188             OSL_ENSURE( aExternalValueType.equals( ::getCppuType( static_cast< double* >( NULL ) ) ),
1189                 "OFormattedModel::translateControlValueToExternalValue: don't know how to translate this type!" );
1190             aExternalValue <<= fValue;
1191         }
1192     }
1193     break;
1194     }
1195     return aExternalValue;
1196 }
1197 
1198 //------------------------------------------------------------------------------
1199 Any OFormattedModel::translateDbColumnToControlValue()
1200 {
1201 	if ( m_bNumeric )
1202 		m_aSaveValue <<= DBTypeConversion::getValue( m_xColumn, m_aNullDate ); // #100056# OJ
1203 	else
1204 		m_aSaveValue <<= m_xColumn->getString();
1205 
1206 	if ( m_xColumn->wasNull() )
1207 		m_aSaveValue.clear();
1208 
1209     return m_aSaveValue;
1210 }
1211 
1212 // -----------------------------------------------------------------------------
1213 Sequence< Type > OFormattedModel::getSupportedBindingTypes()
1214 {
1215     ::std::list< Type > aTypes;
1216     aTypes.push_back( ::getCppuType( static_cast< double* >( NULL ) ) );
1217 
1218     switch ( m_nKeyType & ~NumberFormat::DEFINED )
1219     {
1220     case NumberFormat::DATE:
1221         aTypes.push_front(::getCppuType( static_cast< UNODate* >( NULL ) ) );
1222         break;
1223     case NumberFormat::TIME:
1224         aTypes.push_front(::getCppuType( static_cast< UNOTime* >( NULL ) ) );
1225         break;
1226     case NumberFormat::DATETIME:
1227         aTypes.push_front(::getCppuType( static_cast< UNODateTime* >( NULL ) ) );
1228         break;
1229     case NumberFormat::TEXT:
1230         aTypes.push_front(::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ) );
1231         break;
1232     case NumberFormat::LOGICAL:
1233         aTypes.push_front(::getCppuType( static_cast< sal_Bool* >( NULL ) ) );
1234         break;
1235     }
1236 
1237     Sequence< Type > aTypesRet( aTypes.size() );
1238     ::std::copy( aTypes.begin(), aTypes.end(), aTypesRet.getArray() );
1239     return aTypesRet;
1240 }
1241 
1242 //------------------------------------------------------------------------------
1243 Any OFormattedModel::getDefaultForReset() const
1244 {
1245     return m_xAggregateSet->getPropertyValue( PROPERTY_EFFECTIVE_DEFAULT );
1246 }
1247 
1248 //------------------------------------------------------------------------------
1249 void OFormattedModel::resetNoBroadcast()
1250 {
1251     OEditBaseModel::resetNoBroadcast();
1252     m_aSaveValue.clear();
1253 }
1254 
1255 //.........................................................................
1256 }
1257 //.........................................................................
1258