text:
/**************************************************************
 *
 * 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_extensions.hxx"
#include "standardcontrol.hxx"
#include "pcrcommon.hxx"

/** === begin UNO includes === **/
#include <com/sun/star/util/DateTime.hpp>
#include <com/sun/star/util/Date.hpp>
#include <com/sun/star/util/Time.hpp>
#include <com/sun/star/util/Color.hpp>
#include <com/sun/star/util/MeasureUnit.hpp>
#include <com/sun/star/inspection/PropertyControlType.hpp>
/** === end UNO includes === **/
#include <rtl/math.hxx>
#include <sfx2/objsh.hxx>

//==================================================================
// ugly dependencies for the OColorControl
#ifndef _SVX_SVXIDS_HRC
#include <svx/svxids.hrc>
#endif
#include <svx/drawitem.hxx>
#include <svx/xtable.hxx>
//==================================================================
#include <vcl/floatwin.hxx>
#include <svtools/svmedit.hxx>
#include <svtools/colorcfg.hxx>
#include <unotools/syslocale.hxx>
#include <unotools/datetime.hxx>
#include <i18npool/mslangid.hxx>
#ifndef _SV_BUTTON_HXX
#include <vcl/button.hxx>
#endif
#include <vcl/svapp.hxx>
//==================================================================

#include <memory>
#include <limits>
#include <boost/bind.hpp>

//............................................................................
namespace pcr
{
//............................................................................

    using namespace ::com::sun::star;
    using namespace ::com::sun::star::uno;
    using namespace ::com::sun::star::awt;
    using namespace ::com::sun::star::lang;
    using namespace ::com::sun::star::util;
    using namespace ::com::sun::star::beans;
    using namespace ::com::sun::star::inspection;

	//==================================================================
	//= OTimeControl
	//==================================================================
	//------------------------------------------------------------------
	OTimeControl::OTimeControl( Window* pParent, WinBits nWinStyle )
        :OTimeControl_Base( PropertyControlType::TimeField, pParent, nWinStyle )
    {
		getTypedControlWindow()->SetStrictFormat( sal_True );
		getTypedControlWindow()->SetFormat( TIMEF_SEC );
		getTypedControlWindow()->EnableEmptyFieldValue( sal_True );
	}

	//------------------------------------------------------------------
	void SAL_CALL OTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
        util::Time aUNOTime;
        if ( !( _rValue >>= aUNOTime ) )
		{
			getTypedControlWindow()->SetText( String() );
			getTypedControlWindow()->SetEmptyTime();
		}
		else
		{
            ::Time aTime( aUNOTime.Hours, aUNOTime.Minutes, aUNOTime.Seconds, aUNOTime.HundredthSeconds );
            getTypedControlWindow()->SetTime( aTime );
		}
	}

	//------------------------------------------------------------------
	Any SAL_CALL OTimeControl::getValue() throw (RuntimeException)
	{
        Any aPropValue;
		if ( getTypedControlWindow()->GetText().Len()>0 )
        {
            ::Time aTime( getTypedControlWindow()->GetTime() );
            util::Time aUNOTime( aTime.Get100Sec(), aTime.GetSec(), aTime.GetMin(), aTime.GetHour() );
            aPropValue <<= aUNOTime;
        }
        return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL OTimeControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< util::Time* >( NULL ) );
    }

	//==================================================================
	//= ODateControl
	//==================================================================
	//------------------------------------------------------------------
	ODateControl::ODateControl( Window* pParent, WinBits nWinStyle )
        :ODateControl_Base( PropertyControlType::DateField, pParent, nWinStyle | WB_DROPDOWN )
	{
        WindowType* pControlWindow = getTypedControlWindow();
		pControlWindow->SetStrictFormat(sal_True);

        pControlWindow->SetMin( ::Date( 1,1,1600 ) );
        pControlWindow->SetFirst( ::Date( 1,1,1600 ) );
        pControlWindow->SetLast( ::Date( 1, 1, 9999 ) );
        pControlWindow->SetMax( ::Date( 1, 1, 9999 ) );

		pControlWindow->SetExtDateFormat( XTDATEF_SYSTEM_SHORT_YYYY );
		pControlWindow->EnableEmptyFieldValue( sal_True );
	}

	//------------------------------------------------------------------
	void SAL_CALL ODateControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
        util::Date aUNODate;
        if ( !( _rValue >>= aUNODate ) )
		{
			getTypedControlWindow()->SetText( String() );
			getTypedControlWindow()->SetEmptyDate();
		}
		else
		{
            ::Date aDate( aUNODate.Day, aUNODate.Month, aUNODate.Year );
            getTypedControlWindow()->SetDate( aDate );
		}
	}

	//------------------------------------------------------------------
	Any SAL_CALL ODateControl::getValue() throw (RuntimeException)
	{
        Any aPropValue;
		if ( getTypedControlWindow()->GetText().Len() > 0 )
        {
            ::Date aDate( getTypedControlWindow()->GetDate() );
            util::Date aUNODate( aDate.GetDay(), aDate.GetMonth(), aDate.GetYear() );
            aPropValue <<= aUNODate;
        }
        return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL ODateControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< util::Date* >( NULL ) );
    }

	//==================================================================
	//= OEditControl
	//==================================================================
	//------------------------------------------------------------------
	OEditControl::OEditControl(Window* _pParent, sal_Bool _bPW, WinBits _nWinStyle)
        :OEditControl_Base( _bPW ? PropertyControlType::CharacterField : PropertyControlType::TextField, _pParent, _nWinStyle )
	{
		m_bIsPassword = _bPW;

		if ( m_bIsPassword )
		   getTypedControlWindow()->SetMaxTextLen( 1 );
	}

	//------------------------------------------------------------------
	void SAL_CALL OEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
        ::rtl::OUString sText;
		if ( m_bIsPassword )
        {
            sal_Int16 nValue = 0;
            _rValue >>= nValue;
            if ( nValue )
            {
			    sal_Unicode nCharacter = nValue;
                sText = String( &nCharacter, 1 );
            }
        }
        else
            _rValue >>= sText;

		getTypedControlWindow()->SetText( sText );
	}

	//------------------------------------------------------------------
	Any SAL_CALL OEditControl::getValue() throw (RuntimeException)
	{
        Any aPropValue;

        ::rtl::OUString sText( getTypedControlWindow()->GetText() );
		if ( m_bIsPassword )
		{
			if ( sText.getLength() )
                aPropValue <<= (sal_Int16)sText.getStr()[0];
		}
        else
            aPropValue <<= sText;

		return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL OEditControl::getValueType() throw (RuntimeException)
    {
        return m_bIsPassword ? ::getCppuType( static_cast< sal_Int16* >( NULL ) ) : ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
    }

	//------------------------------------------------------------------
	void OEditControl::modified()
	{
		OEditControl_Base::modified();

		// for pasword controls, we fire a commit for every single change
		if ( m_bIsPassword )
			m_aImplControl.notifyModifiedValue();
	}

	//------------------------------------------------------------------
	static long ImplCalcLongValue( double nValue, sal_uInt16 nDigits )
	{
		double n = nValue;
		for ( sal_uInt16 d = 0; d < nDigits; ++d )
			n *= 10;

        if ( n > ::std::numeric_limits< long >::max() )
            return ::std::numeric_limits< long >::max();
		return (long)n;
	}

	//------------------------------------------------------------------
	static double ImplCalcDoubleValue( long nValue, sal_uInt16 nDigits )
	{
		double n = nValue;
		for ( sal_uInt16 d = 0; d < nDigits; ++d )
			n /= 10;
		return n;
	}

    //==================================================================
	// class ODateTimeControl
	//==================================================================
	//------------------------------------------------------------------
	ODateTimeControl::ODateTimeControl( Window* _pParent, WinBits _nWinStyle)
        :ODateTimeControl_Base( PropertyControlType::DateTimeField, _pParent, _nWinStyle )
	{
		getTypedControlWindow()->EnableEmptyField( sal_True );

        // determine a default format
        Locale aSysLocale = SvtSysLocale().GetLocaleData().getLocale();
        LanguageType eSysLanguage = MsLangId::convertLocaleToLanguage( aSysLocale );

        getTypedControlWindow()->SetFormatter( getTypedControlWindow()->StandardFormatter() );
        SvNumberFormatter* pFormatter = getTypedControlWindow()->GetFormatter();
        sal_uLong nStandardDateTimeFormat = pFormatter->GetStandardFormat( NUMBERFORMAT_DATETIME, eSysLanguage );

        getTypedControlWindow()->SetFormatKey( nStandardDateTimeFormat );
	}

	//------------------------------------------------------------------
    void SAL_CALL ODateTimeControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
    {
		if ( !_rValue.hasValue() )
        {
            getTypedControlWindow()->SetText( String() );
        }
        else
        {
            util::DateTime aUNODateTime;
            OSL_VERIFY( _rValue >>= aUNODateTime );

            ::DateTime aDateTime;
            ::utl::typeConvert( aUNODateTime, aDateTime );

            double nValue = aDateTime - ::DateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );
            getTypedControlWindow()->SetValue( nValue );
        }
    }

	//------------------------------------------------------------------
    Any SAL_CALL ODateTimeControl::getValue() throw (RuntimeException)
    {
        Any aPropValue;
        if ( getTypedControlWindow()->GetText().Len() )
        {
            double nValue = getTypedControlWindow()->GetValue();

            ::DateTime aDateTime( *getTypedControlWindow()->GetFormatter()->GetNullDate() );

            // add the "days" part
            double nDays = floor( nValue );
            aDateTime += nDays;

            // add the "time" part
            double nTime = nValue - nDays;
            nTime = ::rtl::math::round( nTime * 86400.0 ) / 86400.0;
                // we're not interested in 100th seconds, and this here prevents rounding errors
            aDateTime += nTime;

            util::DateTime aUNODateTime;
            ::utl::typeConvert( aDateTime, aUNODateTime );

            aPropValue <<= aUNODateTime;
        }
        return aPropValue;
    }

	//------------------------------------------------------------------
    Type SAL_CALL ODateTimeControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< util::DateTime* >( NULL ) );
    }

    //========================================================================
    //= HyperlinkInput
    //========================================================================
    //--------------------------------------------------------------------
    HyperlinkInput::HyperlinkInput( Window* _pParent, WinBits _nWinStyle )
        :Edit( _pParent, _nWinStyle )
    {
        ::svtools::ColorConfig aColorConfig;
        ::svtools::ColorConfigValue aLinkColor( aColorConfig.GetColorValue( ::svtools::LINKS ) );

        AllSettings aAllSettings( GetSettings() );
        StyleSettings aStyleSettings( aAllSettings.GetStyleSettings() );

        Font aFieldFont( aStyleSettings.GetFieldFont() );
        aFieldFont.SetUnderline( UNDERLINE_SINGLE );
        aFieldFont.SetColor( aLinkColor.nColor );
        aStyleSettings.SetFieldFont( aFieldFont );

        aStyleSettings.SetFieldTextColor( aLinkColor.nColor );

        aAllSettings.SetStyleSettings( aStyleSettings );
        SetSettings( aAllSettings );
    }

    //--------------------------------------------------------------------
    void HyperlinkInput::MouseMove( const ::MouseEvent& rMEvt )
    {
        Edit::MouseMove( rMEvt );

        PointerStyle ePointerStyle( POINTER_TEXT );

        if ( !rMEvt.IsLeaveWindow() )
        {
            if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
                ePointerStyle = POINTER_REFHAND;
        }

        SetPointer( Pointer( ePointerStyle ) );
    }

    //--------------------------------------------------------------------
    void HyperlinkInput::MouseButtonDown( const ::MouseEvent& rMEvt )
    {
        Edit::MouseButtonDown( rMEvt );

        if ( impl_textHitTest( rMEvt.GetPosPixel() ) )
            m_aMouseButtonDownPos = rMEvt.GetPosPixel();
        else
            m_aMouseButtonDownPos.X() = m_aMouseButtonDownPos.Y() = -1;
    }

    //--------------------------------------------------------------------
    void HyperlinkInput::MouseButtonUp( const ::MouseEvent& rMEvt )
    {
        Edit::MouseButtonUp( rMEvt );

        impl_checkEndClick( rMEvt );
    }

    //--------------------------------------------------------------------
    bool HyperlinkInput::impl_textHitTest( const ::Point& _rWindowPos )
    {
        xub_StrLen nPos = GetCharPos( _rWindowPos );
        return ( ( nPos != STRING_LEN ) && ( nPos < GetText().Len() ) );
    }

    //--------------------------------------------------------------------
    void HyperlinkInput::impl_checkEndClick( const ::MouseEvent rMEvt )
    {
        const MouseSettings& rMouseSettings( GetSettings().GetMouseSettings() );
        if  (   ( abs( rMEvt.GetPosPixel().X() - m_aMouseButtonDownPos.X() ) < rMouseSettings.GetStartDragWidth() )
            &&  ( abs( rMEvt.GetPosPixel().Y() - m_aMouseButtonDownPos.Y() ) < rMouseSettings.GetStartDragHeight() )
            )
            Application::PostUserEvent( m_aClickHandler );
    }

    //--------------------------------------------------------------------
    void HyperlinkInput::Tracking( const TrackingEvent& rTEvt )
    {
        Edit::Tracking( rTEvt );

        if ( rTEvt.IsTrackingEnded() )
            impl_checkEndClick( rTEvt.GetMouseEvent() );
    }

    //========================================================================
    //= OHyperlinkControl
    //========================================================================
    //--------------------------------------------------------------------
    OHyperlinkControl::OHyperlinkControl( Window* _pParent, WinBits _nWinStyle )
        :OHyperlinkControl_Base( PropertyControlType::HyperlinkField, _pParent, _nWinStyle )
        ,m_aActionListeners( m_aMutex )
    {
        getTypedControlWindow()->SetClickHdl( LINK( this, OHyperlinkControl, OnHyperlinkClicked ) );
    }

    //--------------------------------------------------------------------
    Any SAL_CALL OHyperlinkControl::getValue() throw (RuntimeException)
    {
        ::rtl::OUString sText = getTypedControlWindow()->GetText();
        return makeAny( sText );
    }

    //--------------------------------------------------------------------
    void SAL_CALL OHyperlinkControl::setValue( const Any& _value ) throw (IllegalTypeException, RuntimeException)
    {
        ::rtl::OUString sText;
        _value >>= sText;
        getTypedControlWindow()->SetText( sText );
    }

    //--------------------------------------------------------------------
    Type SAL_CALL OHyperlinkControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
    }

    //--------------------------------------------------------------------
    void SAL_CALL OHyperlinkControl::addActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException)
    {
        if ( listener.is() )
            m_aActionListeners.addInterface( listener );
    }

    //--------------------------------------------------------------------
    void SAL_CALL OHyperlinkControl::removeActionListener( const Reference< XActionListener >& listener ) throw (RuntimeException)
    {
        m_aActionListeners.removeInterface( listener );
    }

	//------------------------------------------------------------------
    void SAL_CALL OHyperlinkControl::disposing()
    {
        OHyperlinkControl_Base::disposing();

        EventObject aEvent( *this );
        m_aActionListeners.disposeAndClear( aEvent );
    }

	//------------------------------------------------------------------
    IMPL_LINK( OHyperlinkControl, OnHyperlinkClicked, void*, /*_NotInterestedIn*/ )
    {
        ActionEvent aEvent( *this, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "clicked" ) ) );
        m_aActionListeners.forEach< XActionListener >(
            boost::bind(
                &XActionListener::actionPerformed,
                _1, boost::cref(aEvent) ) );

        return 0;
    }

    //==================================================================
	//= ONumericControl
	//==================================================================
	//------------------------------------------------------------------
	ONumericControl::ONumericControl( Window* _pParent, WinBits _nWinStyle )
        :ONumericControl_Base( PropertyControlType::NumericField, _pParent, _nWinStyle )
        ,m_eValueUnit( FUNIT_NONE )
        ,m_nFieldToUNOValueFactor( 1 )
	{
        getTypedControlWindow()->SetDefaultUnit( FUNIT_NONE );

		getTypedControlWindow()->EnableEmptyFieldValue( sal_True );
		getTypedControlWindow()->SetStrictFormat( sal_True );
        Optional< double > value( getMaxValue() );
        value.Value = -value.Value;
        setMinValue( value );
	}

    //--------------------------------------------------------------------
    ::sal_Int16 SAL_CALL ONumericControl::getDecimalDigits() throw (RuntimeException)
    {
        return getTypedControlWindow()->GetDecimalDigits();
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setDecimalDigits( ::sal_Int16 _decimaldigits ) throw (RuntimeException)
    {
        getTypedControlWindow()->SetDecimalDigits( _decimaldigits );
    }

    //--------------------------------------------------------------------
    Optional< double > SAL_CALL ONumericControl::getMinValue() throw (RuntimeException)
    {
        Optional< double > aReturn( sal_True, 0 );

        sal_Int64 minValue = getTypedControlWindow()->GetMin();
        if ( minValue == ::std::numeric_limits< sal_Int64 >::min() )
            aReturn.IsPresent = sal_False;
        else
            aReturn.Value = (double)minValue;

        return aReturn;
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setMinValue( const Optional< double >& _minvalue ) throw (RuntimeException)
    {
        if ( !_minvalue.IsPresent )
            getTypedControlWindow()->SetMin( ::std::numeric_limits< sal_Int64 >::min() );
        else
            getTypedControlWindow()->SetMin( impl_apiValueToFieldValue_nothrow( _minvalue.Value ) , m_eValueUnit);
    }

    //--------------------------------------------------------------------
    Optional< double > SAL_CALL ONumericControl::getMaxValue() throw (RuntimeException)
    {
        Optional< double > aReturn( sal_True, 0 );

        sal_Int64 maxValue = getTypedControlWindow()->GetMax();
        if ( maxValue == ::std::numeric_limits< sal_Int64 >::max() )
            aReturn.IsPresent = sal_False;
        else
            aReturn.Value = (double)maxValue;

        return aReturn;
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setMaxValue( const Optional< double >& _maxvalue ) throw (RuntimeException)
    {
        if ( !_maxvalue.IsPresent )
            getTypedControlWindow()->SetMax( ::std::numeric_limits< sal_Int64 >::max() );
        else
            getTypedControlWindow()->SetMax( impl_apiValueToFieldValue_nothrow( _maxvalue.Value ), m_eValueUnit );
    }

    //--------------------------------------------------------------------
    ::sal_Int16 SAL_CALL ONumericControl::getDisplayUnit() throw (RuntimeException)
    {
        return VCLUnoHelper::ConvertToMeasurementUnit( getTypedControlWindow()->GetUnit(), 1 );
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setDisplayUnit( ::sal_Int16 _displayunit ) throw (IllegalArgumentException, RuntimeException)
    {
        if ( ( _displayunit < MeasureUnit::MM_100TH ) || ( _displayunit > MeasureUnit::PERCENT ) )
            throw IllegalArgumentException();
        if  (   ( _displayunit == MeasureUnit::MM_100TH )
            ||  ( _displayunit == MeasureUnit::MM_10TH )
            ||  ( _displayunit == MeasureUnit::INCH_1000TH )
            ||  ( _displayunit == MeasureUnit::INCH_100TH )
            ||  ( _displayunit == MeasureUnit::INCH_10TH )
            ||  ( _displayunit == MeasureUnit::PERCENT )
            )
            throw IllegalArgumentException();

        sal_Int16 nDummyFactor = 1;
        FieldUnit eFieldUnit = VCLUnoHelper::ConvertToFieldUnit( _displayunit, nDummyFactor );
        if ( nDummyFactor != 1 )
            // everything which survived the checks above should result in a factor of 1, i.e.,
            // it should have a direct counterpart as FieldUnit
            throw RuntimeException();
        getTypedControlWindow()->SetUnit( eFieldUnit );
    }

    //--------------------------------------------------------------------
    ::sal_Int16 SAL_CALL ONumericControl::getValueUnit() throw (RuntimeException)
    {
        return VCLUnoHelper::ConvertToMeasurementUnit( m_eValueUnit, m_nFieldToUNOValueFactor );
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setValueUnit( ::sal_Int16 _valueunit ) throw (RuntimeException)
    {
        if ( ( _valueunit < MeasureUnit::MM_100TH ) || ( _valueunit > MeasureUnit::PERCENT ) )
            throw IllegalArgumentException();
        m_eValueUnit = VCLUnoHelper::ConvertToFieldUnit( _valueunit, m_nFieldToUNOValueFactor );
    }

    //--------------------------------------------------------------------
    void SAL_CALL ONumericControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
		if ( !_rValue.hasValue() )
		{
			getTypedControlWindow()->SetText( String() );
			getTypedControlWindow()->SetEmptyFieldValue();
		}
		else
		{
            double nValue( 0 );
            OSL_VERIFY( _rValue >>= nValue );
            long nControlValue = impl_apiValueToFieldValue_nothrow( nValue );
            getTypedControlWindow()->SetValue( nControlValue, m_eValueUnit );
		}
	}

	//------------------------------------------------------------------
    long ONumericControl::impl_apiValueToFieldValue_nothrow( double _nApiValue ) const
    {
        long nControlValue = ImplCalcLongValue( _nApiValue, getTypedControlWindow()->GetDecimalDigits() );
        nControlValue /= m_nFieldToUNOValueFactor;
        return nControlValue;
    }

	//------------------------------------------------------------------
    double ONumericControl::impl_fieldValueToApiValue_nothrow( sal_Int64 _nFieldValue ) const
    {
		double nApiValue = ImplCalcDoubleValue( (long)_nFieldValue, getTypedControlWindow()->GetDecimalDigits() );
        nApiValue *= m_nFieldToUNOValueFactor;
        return nApiValue;
    }

	//------------------------------------------------------------------
	Any SAL_CALL ONumericControl::getValue() throw (RuntimeException)
	{
        Any aPropValue;
		if ( getTypedControlWindow()->GetText().Len() )
        {
            double nValue = impl_fieldValueToApiValue_nothrow( getTypedControlWindow()->GetValue( m_eValueUnit ) );
            aPropValue <<= nValue;
        }
        return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL ONumericControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< double* >( NULL ) );
    }

	//==================================================================
	//= OColorControl
	//==================================================================
	#define LB_DEFAULT_COUNT 20
	//------------------------------------------------------------------
	String MakeHexStr(sal_uInt32 nVal, sal_uInt32 nLength)
	{
		String aStr;
		while (nVal>0)
		{
			char c=char(nVal & 0x000F);
			nVal>>=4;
			if (c<=9) c+='0';
			else c+='A'-10;
			aStr.Insert(c,0);
		}
		while (aStr.Len() < nLength) aStr.Insert('0',0);
		return aStr;
	}

	//------------------------------------------------------------------
	OColorControl::OColorControl(Window* pParent, WinBits nWinStyle)
        :OColorControl_Base( PropertyControlType::ColorListBox, pParent, nWinStyle )
	{
		// initialize the color listbox
        XColorListSharedPtr aColorTable;
        SfxObjectShell* pDocSh = SfxObjectShell::Current();
        const SfxPoolItem* pItem = pDocSh ? pDocSh->GetItem( SID_COLOR_TABLE ) : NULL;
        if ( pItem )
        {
            DBG_ASSERT(pItem->ISA(SvxColorTableItem), "OColorControl::OColorControl: invalid color item!");
		    aColorTable = static_cast< const SvxColorTableItem* >(pItem)->GetColorTable();
        }

        if ( !aColorTable.get() )
	    {
		    aColorTable = XColorList::GetStdColorList();
	    }

		DBG_ASSERT(aColorTable.get(), "OColorControl::OColorControl: no color table!");

		if (aColorTable.get())
		{
			for (sal_uInt16 i = 0; i < aColorTable->Count(); ++i)
			{
				XColorEntry* pEntry = aColorTable->GetColor( i );
				getTypedControlWindow()->InsertEntry( pEntry->GetColor(), pEntry->GetName() );
			}
		}

		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
        if ( ( nWinStyle & WB_READONLY ) != 0 )
        {
            getTypedControlWindow()->SetReadOnly( sal_True );
            getTypedControlWindow()->Enable( sal_True );
        }
	}

	//------------------------------------------------------------------
	void SAL_CALL OColorControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
		if ( _rValue.hasValue() )
        {
            ::com::sun::star::util::Color nColor = COL_TRANSPARENT;
            if ( _rValue >>= nColor )
            {
                ::Color aRgbCol((ColorData)nColor);

				getTypedControlWindow()->SelectEntry( aRgbCol );
				if ( !getTypedControlWindow()->IsEntrySelected( aRgbCol ) )
				{	// the given color is not part of the list -> insert a new entry with the hex code of the color
					String aStr = String::CreateFromAscii("0x");
					aStr += MakeHexStr(nColor,8);
					getTypedControlWindow()->InsertEntry( aRgbCol, aStr );
					getTypedControlWindow()->SelectEntry( aRgbCol );
				}
            }
            else
            {
                ::rtl::OUString sNonColorValue;
                if ( !( _rValue >>= sNonColorValue ) )
                    throw IllegalTypeException();
                getTypedControlWindow()->SelectEntry( sNonColorValue );
                if ( !getTypedControlWindow()->IsEntrySelected( sNonColorValue ) )
                    getTypedControlWindow()->SetNoSelection();
            }
		}
		else
			getTypedControlWindow()->SetNoSelection();
	}

	//------------------------------------------------------------------
	Any SAL_CALL OColorControl::getValue() throw (RuntimeException)
	{
        Any aPropValue;
		if ( getTypedControlWindow()->GetSelectEntryCount() > 0 )
		{
            ::rtl::OUString sSelectedEntry = getTypedControlWindow()->GetSelectEntry();
            if ( m_aNonColorEntries.find( sSelectedEntry ) != m_aNonColorEntries.end() )
                aPropValue <<= sSelectedEntry;
            else
			{
                ::Color aRgbCol = getTypedControlWindow()->GetSelectEntryColor();
                aPropValue <<= (::com::sun::star::util::Color)aRgbCol.GetColor();
			}
		}
		return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL OColorControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< sal_Int32* >( NULL ) );
    }

	//------------------------------------------------------------------
	void SAL_CALL OColorControl::clearList() throw (RuntimeException)
	{
		getTypedControlWindow()->Clear();
	}

	//------------------------------------------------------------------
	void SAL_CALL OColorControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
        m_aNonColorEntries.insert( NewEntry );
	}

	//------------------------------------------------------------------
	void SAL_CALL OColorControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry );
        m_aNonColorEntries.insert( NewEntry );
	}
    //------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL OColorControl::getListEntries(  ) throw (RuntimeException)
    {
        if ( !m_aNonColorEntries.empty() )
            return Sequence< ::rtl::OUString >(&(*m_aNonColorEntries.begin()),m_aNonColorEntries.size());
        return Sequence< ::rtl::OUString >();
    }

	//------------------------------------------------------------------
	void OColorControl::modified()
	{
		OColorControl_Base::modified();

		if ( !getTypedControlWindow()->IsTravelSelect() )
			// fire a commit
			m_aImplControl.notifyModifiedValue();
	}

	//==================================================================
	//= OListboxControl
	//==================================================================
	//------------------------------------------------------------------
	OListboxControl::OListboxControl( Window* pParent, WinBits nWinStyle)
        :OListboxControl_Base( PropertyControlType::ListBox, pParent, nWinStyle )
	{
		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
        if ( ( nWinStyle & WB_READONLY ) != 0 )
        {
            getTypedControlWindow()->SetReadOnly( sal_True );
            getTypedControlWindow()->Enable( sal_True );
        }
	}

	//------------------------------------------------------------------
	Any SAL_CALL OListboxControl::getValue() throw (RuntimeException)
	{
        ::rtl::OUString sControlValue( getTypedControlWindow()->GetSelectEntry() );

        Any aPropValue;
        if ( sControlValue.getLength() )
            aPropValue <<= sControlValue;
		return aPropValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL OListboxControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
    }

	//------------------------------------------------------------------
	void SAL_CALL OListboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
		if ( !_rValue.hasValue() )
            getTypedControlWindow()->SetNoSelection();
        else
		{
            ::rtl::OUString sSelection;
            _rValue >>= sSelection;

            if ( !sSelection.equals( getTypedControlWindow()->GetSelectEntry() ) )
				getTypedControlWindow()->SelectEntry( sSelection );

			if ( !getTypedControlWindow()->IsEntrySelected( sSelection ) )
			{
				getTypedControlWindow()->InsertEntry( sSelection, 0 );
				getTypedControlWindow()->SelectEntry( sSelection );
			}
		}
	}

	//------------------------------------------------------------------
	void SAL_CALL OListboxControl::clearList() throw (RuntimeException)
	{
		getTypedControlWindow()->Clear();
	}

	//------------------------------------------------------------------
	void SAL_CALL OListboxControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
	}

	//------------------------------------------------------------------
	void SAL_CALL OListboxControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry );
	}
    //------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL OListboxControl::getListEntries(  ) throw (RuntimeException)
    {
        const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
        Sequence< ::rtl::OUString > aRet(nCount);
        ::rtl::OUString* pIter = aRet.getArray();
        for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
            *pIter = getTypedControlWindow()->GetEntry(i);

        return aRet;
    }

	//------------------------------------------------------------------
	void OListboxControl::modified()
	{
		OListboxControl_Base::modified();

		if ( !getTypedControlWindow()->IsTravelSelect() )
			// fire a commit
			m_aImplControl.notifyModifiedValue();
	}

	//==================================================================
	//= OComboboxControl
	//==================================================================
	//------------------------------------------------------------------
	OComboboxControl::OComboboxControl( Window* pParent, WinBits nWinStyle)
        :OComboboxControl_Base( PropertyControlType::ComboBox, pParent, nWinStyle )
    {
		getTypedControlWindow()->SetDropDownLineCount( LB_DEFAULT_COUNT );
        getTypedControlWindow()->SetSelectHdl( LINK( this, OComboboxControl, OnEntrySelected ) );
	}

	//------------------------------------------------------------------
	void SAL_CALL OComboboxControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
		::rtl::OUString sText;
        _rValue >>= sText;
		getTypedControlWindow()->SetText( sText );
	}

	//------------------------------------------------------------------
	Any SAL_CALL OComboboxControl::getValue() throw (RuntimeException)
	{
        return makeAny( ::rtl::OUString( getTypedControlWindow()->GetText() ) );
	}

	//------------------------------------------------------------------
    Type SAL_CALL OComboboxControl::getValueType() throw (RuntimeException)
    {
        return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
    }

	//------------------------------------------------------------------
	void SAL_CALL OComboboxControl::clearList() throw (RuntimeException)
	{
		getTypedControlWindow()->Clear();
	}

	//------------------------------------------------------------------
	void SAL_CALL OComboboxControl::prependListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry, 0 );
	}

	//------------------------------------------------------------------
	void SAL_CALL OComboboxControl::appendListEntry( const ::rtl::OUString& NewEntry ) throw (RuntimeException)
	{
		getTypedControlWindow()->InsertEntry( NewEntry );
	}
    //------------------------------------------------------------------
    Sequence< ::rtl::OUString > SAL_CALL OComboboxControl::getListEntries(  ) throw (RuntimeException)
    {
        const sal_uInt16 nCount = getTypedControlWindow()->GetEntryCount();
        Sequence< ::rtl::OUString > aRet(nCount);
        ::rtl::OUString* pIter = aRet.getArray();
        for (sal_uInt16 i = 0; i < nCount ; ++i,++pIter)
            *pIter = getTypedControlWindow()->GetEntry(i);

        return aRet;
    }

	//------------------------------------------------------------------
    IMPL_LINK( OComboboxControl, OnEntrySelected, void*, /*_pNothing*/ )
	{
		if ( !getTypedControlWindow()->IsTravelSelect() )
			// fire a commit
			m_aImplControl.notifyModifiedValue();
        return 0L;
	}

	//==================================================================
	//= OMultilineFloatingEdit
	//==================================================================
	class OMultilineFloatingEdit : public FloatingWindow
	{
	private:
		MultiLineEdit	m_aImplEdit;

	protected:
		virtual void	Resize();

	public:
						OMultilineFloatingEdit(Window* _pParen);
		MultiLineEdit*  getEdit() { return &m_aImplEdit; }

	protected:
		virtual long	PreNotify(NotifyEvent& _rNEvt);
	};

	//------------------------------------------------------------------
	OMultilineFloatingEdit::OMultilineFloatingEdit(Window* _pParent)
		:FloatingWindow(_pParent, WB_BORDER)
		,m_aImplEdit(this, WB_VSCROLL|WB_IGNORETAB|WB_NOBORDER)
	{
		m_aImplEdit.Show();
	}

	//------------------------------------------------------------------
	void OMultilineFloatingEdit::Resize()
	{
		m_aImplEdit.SetSizePixel(GetOutputSizePixel());
	}

	//------------------------------------------------------------------
	long OMultilineFloatingEdit::PreNotify(NotifyEvent& _rNEvt)
	{
		long nResult = sal_True;

		sal_uInt16 nSwitch = _rNEvt.GetType();
		if (EVENT_KEYINPUT == nSwitch)
		{
			const KeyCode& aKeyCode = _rNEvt.GetKeyEvent()->GetKeyCode();
			sal_uInt16 nKey = aKeyCode.GetCode();

			if	(	(	(KEY_RETURN == nKey)
					&& !aKeyCode.IsShift()
					)
				||	(	(KEY_UP == nKey)
					&&	aKeyCode.IsMod2()
					)
				)
			{
				EndPopupMode();
			}
			else
				nResult=FloatingWindow::PreNotify(_rNEvt);
		}
		else
			nResult=FloatingWindow::PreNotify(_rNEvt);

		return nResult;
	}

	//==================================================================
	//= DropDownEditControl_Base
	//==================================================================
	//------------------------------------------------------------------
    DropDownEditControl::DropDownEditControl( Window* _pParent, WinBits _nStyle )
        :DropDownEditControl_Base( _pParent, _nStyle )
		,m_pFloatingEdit( NULL )
		,m_pImplEdit( NULL )
		,m_pDropdownButton( NULL )
        ,m_nOperationMode( eStringList )
		,m_bDropdown( sal_False )
    {
        SetCompoundControl( sal_True );

		m_pImplEdit = new MultiLineEdit( this, WB_TABSTOP | WB_IGNORETAB | WB_NOBORDER | (_nStyle & WB_READONLY) );
        SetSubEdit( m_pImplEdit );
		m_pImplEdit->Show();

		if ( _nStyle & WB_DROPDOWN )
		{
			m_pDropdownButton = new PushButton( this, WB_NOLIGHTBORDER | WB_RECTSTYLE | WB_NOTABSTOP);
			m_pDropdownButton->SetSymbol(SYMBOL_SPIN_DOWN);
			m_pDropdownButton->SetClickHdl( LINK( this, DropDownEditControl, DropDownHdl ) );
			m_pDropdownButton->Show();
		}

		m_pFloatingEdit = new OMultilineFloatingEdit(this); //FloatingWindow

		m_pFloatingEdit->SetPopupModeEndHdl( LINK( this, DropDownEditControl, ReturnHdl ) );
        m_pFloatingEdit->getEdit()->SetReadOnly( ( _nStyle & WB_READONLY ) != 0 );
    }

	//------------------------------------------------------------------
    void DropDownEditControl::setControlHelper( ControlHelper& _rControlHelper )
    {
        DropDownEditControl_Base::setControlHelper( _rControlHelper );
		m_pFloatingEdit->getEdit()->SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
		m_pImplEdit->SetGetFocusHdl( LINK( &_rControlHelper, ControlHelper, GetFocusHdl ) );
		m_pImplEdit->SetModifyHdl( LINK( &_rControlHelper, ControlHelper, ModifiedHdl ) );
		m_pImplEdit->SetLoseFocusHdl( LINK( &_rControlHelper, ControlHelper, LoseFocusHdl ) );
    }

	//------------------------------------------------------------------
	DropDownEditControl::~DropDownEditControl()
	{
		{
			::std::auto_ptr<Window> aTemp(m_pFloatingEdit);
			m_pFloatingEdit = NULL;
		}
		{
			::std::auto_ptr<Window> aTemp(m_pImplEdit);
            SetSubEdit( NULL );
			m_pImplEdit = NULL;
		}
		{
			::std::auto_ptr<Window> aTemp(m_pDropdownButton);
			m_pDropdownButton = NULL;
		}
	}

	//------------------------------------------------------------------
	void DropDownEditControl::Resize()
	{
        ::Size aOutSz = GetOutputSizePixel();

		if (m_pDropdownButton!=NULL)
		{
			long nSBWidth = GetSettings().GetStyleSettings().GetScrollBarSize();
			nSBWidth = CalcZoom( nSBWidth );
			m_pImplEdit->SetPosSizePixel( 0, 1, aOutSz.Width() - nSBWidth, aOutSz.Height()-2 );
			m_pDropdownButton->SetPosSizePixel( aOutSz.Width() - nSBWidth, 0, nSBWidth, aOutSz.Height() );
		}
		else
			m_pImplEdit->SetPosSizePixel( 0, 1, aOutSz.Width(), aOutSz.Height()-2 );
	}

	//------------------------------------------------------------------
	long DropDownEditControl::PreNotify( NotifyEvent& rNEvt )
	{
		long nResult = 1;

		if (rNEvt.GetType() == EVENT_KEYINPUT)
		{
			const KeyCode& aKeyCode = rNEvt.GetKeyEvent()->GetKeyCode();
			sal_uInt16 nKey = aKeyCode.GetCode();

			if ( nKey == KEY_RETURN && !aKeyCode.IsShift() )
			{
                if ( m_pHelper )
                {
				    m_pHelper->LoseFocusHdl( m_pImplEdit );
                    m_pHelper->activateNextControl();
                }
			}
			else if ( nKey == KEY_DOWN && aKeyCode.IsMod2() )
			{
				Invalidate();
				ShowDropDown( sal_True );
			}
			else if (   KEYGROUP_CURSOR == aKeyCode.GetGroup()
                    ||  nKey == KEY_HELP
                    ||  KEYGROUP_FKEYS == aKeyCode.GetGroup()
                    ||  m_nOperationMode == eMultiLineText
                    )
			{
                nResult = DropDownEditControl_Base::PreNotify( rNEvt );
			}
			else if ( m_nOperationMode == eStringList )
			{
				Selection aSel = m_pImplEdit->GetSelection();
				if ( aSel.Min() != aSel.Max() )
				{
					aSel.Min() = FindPos( aSel.Min() );
					aSel.Max() = FindPos( aSel.Max() );
				}
				else
				{
					aSel.Min() = FindPos( aSel.Min() );
					aSel.Max() = aSel.Min();
				}
				Invalidate();
				ShowDropDown( sal_True );
				m_pFloatingEdit->getEdit()->GrabFocus();
				m_pFloatingEdit->getEdit()->SetSelection( aSel );
				Window*	pFocusWin = Application::GetFocusWindow();
				pFocusWin->KeyInput( *rNEvt.GetKeyEvent() );
			}
		}
		else
			nResult = DropDownEditControl_Base::PreNotify(rNEvt);

		return nResult;
	}

	//------------------------------------------------------------------
    namespace
    {
	    //..............................................................
        StlSyntaxSequence< ::rtl::OUString > lcl_convertMultiLineToList( const String& _rCompsedTextWithLineBreaks )
        {
            xub_StrLen nLines( _rCompsedTextWithLineBreaks.GetTokenCount( '\n' ) );
            StlSyntaxSequence< ::rtl::OUString > aStrings( nLines );
            StlSyntaxSequence< ::rtl::OUString >::iterator stringItem = aStrings.begin();
            for ( xub_StrLen token = 0; token < nLines; ++token, ++stringItem )
                *stringItem = _rCompsedTextWithLineBreaks.GetToken( token, '\n' );
            return aStrings;
        }

        String lcl_convertListToMultiLine( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
        {
            String sMultiLineText;
            for (   StlSyntaxSequence< ::rtl::OUString >::const_iterator item = _rStrings.begin();
                    item != _rStrings.end();
                )
            {
                sMultiLineText += String( *item );
                if ( ++item != _rStrings.end() )
                    sMultiLineText += '\n';
            }
            return sMultiLineText;
        }

        //..............................................................
        String lcl_convertListToDisplayText( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
        {
            ::rtl::OUStringBuffer aComposed;
            for (   StlSyntaxSequence< ::rtl::OUString >::const_iterator strings = _rStrings.begin();
                    strings != _rStrings.end();
                    ++strings
                )
            {
                if ( strings != _rStrings.begin() )
                    aComposed.append( (sal_Unicode)';' );
                aComposed.append( (sal_Unicode)'\"' );
                aComposed.append( *strings );
                aComposed.append( (sal_Unicode)'\"' );
            }
            return aComposed.makeStringAndClear();
        }
    }

	//------------------------------------------------------------------
	#define STD_HEIGHT	100
	sal_Bool DropDownEditControl::ShowDropDown( sal_Bool bShow )
	{
		if (bShow)
		{
            ::Point aMePos= GetPosPixel();
			aMePos = GetParent()->OutputToScreenPixel( aMePos );
            ::Size aSize=GetSizePixel();
            ::Rectangle aRect(aMePos,aSize);
			aSize.Height() = STD_HEIGHT;
			m_pFloatingEdit->SetOutputSizePixel(aSize);
			m_pFloatingEdit->StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN );

			m_pFloatingEdit->Show();
			m_pFloatingEdit->getEdit()->GrabFocus();
			m_pFloatingEdit->getEdit()->SetSelection(Selection(m_pFloatingEdit->getEdit()->GetText().Len()));
			m_bDropdown=sal_True;
			if ( m_nOperationMode == eMultiLineText )
				m_pFloatingEdit->getEdit()->SetText( m_pImplEdit->GetText() );
			m_pImplEdit->SetText(String());
		}
		else
		{
			m_pFloatingEdit->Hide();
			m_pFloatingEdit->Invalidate();
			m_pFloatingEdit->Update();

            // transfer the text from the floating edit to our own edit
			String sDisplayText( m_pFloatingEdit->getEdit()->GetText() );
            if ( m_nOperationMode == eStringList )
                sDisplayText = lcl_convertListToDisplayText( lcl_convertMultiLineToList( sDisplayText ) );

			m_pImplEdit->SetText( sDisplayText );
			GetParent()->Invalidate( INVALIDATE_CHILDREN );
			m_bDropdown = sal_False;
			m_pImplEdit->GrabFocus();
		}
		return m_bDropdown;

	}

	//------------------------------------------------------------------
	long DropDownEditControl::FindPos(long nSinglePos)
	{
		long nPos=0;
		long nDiff=0;
		String aOutput;
		String aStr=m_pFloatingEdit->getEdit()->GetText();
		String aStr1 = GetText();

		if ((nSinglePos == 0) || (nSinglePos == aStr1.Len()))
		{
			return nSinglePos;
		}

		if (aStr.Len()>0)
		{
			sal_Int32 nCount = aStr.GetTokenCount('\n');

			String aInput = aStr.GetToken(0,'\n' );

			if (aInput.Len()>0)
			{
				aOutput+='\"';
				nDiff++;
				aOutput+=aInput;
				aOutput+='\"';
			}

			if (nSinglePos <= aOutput.Len())
			{
				nPos=nSinglePos-nDiff;
			}
			else
			{
				for (sal_Int32 i=1; i<nCount; ++i)
				{
					aInput=aStr.GetToken((sal_uInt16)i, '\n');
					if (aInput.Len()>0)
					{
						aOutput += ';';
						aOutput += '\"';
						nDiff += 2;
						aOutput += aInput;
						aOutput += '\"';

						if (nSinglePos <= aOutput.Len())
						{
							nPos=nSinglePos-nDiff;
							break;
						}
					}
				}
			}
		}
		return nPos;
	}

	//------------------------------------------------------------------
	IMPL_LINK( DropDownEditControl, ReturnHdl, OMultilineFloatingEdit*, /*pMEd*/)
	{

		String aStr = m_pFloatingEdit->getEdit()->GetText();
		String aStr2 = GetText();
		ShowDropDown(sal_False);

		if (aStr!=aStr2 || ( m_nOperationMode == eStringList ) )
		{
			if ( m_pHelper )
			    m_pHelper->notifyModifiedValue();
		}

		return 0;
	}

	//------------------------------------------------------------------
	IMPL_LINK( DropDownEditControl, DropDownHdl, PushButton*, /*pPb*/ )
	{
		ShowDropDown(!m_bDropdown);
		return 0;
	}

	//------------------------------------------------------------------
    void DropDownEditControl::SetStringListValue( const StlSyntaxSequence< ::rtl::OUString >& _rStrings )
    {
		SetText( lcl_convertListToDisplayText( _rStrings ) );
        m_pFloatingEdit->getEdit()->SetText( lcl_convertListToMultiLine( _rStrings ) );
    }

	//------------------------------------------------------------------
    StlSyntaxSequence< ::rtl::OUString > DropDownEditControl::GetStringListValue() const
    {
        return lcl_convertMultiLineToList( m_pFloatingEdit->getEdit()->GetText() );
    }

	//------------------------------------------------------------------
    void DropDownEditControl::SetTextValue( const ::rtl::OUString& _rText )
    {
        OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::SetTextValue: illegal call!" );

        m_pFloatingEdit->getEdit()->SetText( _rText );
		SetText( _rText );
    }

	//------------------------------------------------------------------
    ::rtl::OUString DropDownEditControl::GetTextValue() const
    {
        OSL_PRECOND( m_nOperationMode == eMultiLineText, "DropDownEditControl::GetTextValue: illegal call!" );
        return GetText();
    }

    //==================================================================
	//= OMultilineEditControl
	//==================================================================
	//------------------------------------------------------------------
	OMultilineEditControl::OMultilineEditControl( Window* pParent, MultiLineOperationMode _eMode, WinBits nWinStyle )
        :OMultilineEditControl_Base( _eMode == eMultiLineText ? PropertyControlType::MultiLineTextField : PropertyControlType::StringListField
                                   , pParent
                                   , ( nWinStyle | WB_DIALOGCONTROL ) & ( ~WB_READONLY | ~WB_DROPDOWN )
                                   , false )
	{
        getTypedControlWindow()->setOperationMode( _eMode );
	}

	//------------------------------------------------------------------
	void SAL_CALL OMultilineEditControl::setValue( const Any& _rValue ) throw (IllegalTypeException, RuntimeException)
	{
        impl_checkDisposed_throw();

        switch ( getTypedControlWindow()->getOperationMode() )
        {
        case eMultiLineText:
        {
            ::rtl::OUString sText;
            if ( !( _rValue >>= sText ) && _rValue.hasValue() )
                throw IllegalTypeException();
            getTypedControlWindow()->SetTextValue( sText );
        }
        break;
        case eStringList:
        {
            Sequence< ::rtl::OUString > aStringLines;
            if ( !( _rValue >>= aStringLines ) && _rValue.hasValue() )
                throw IllegalTypeException();
            getTypedControlWindow()->SetStringListValue( aStringLines );
        }
        break;
        }
	}

	//------------------------------------------------------------------
	Any SAL_CALL OMultilineEditControl::getValue() throw (RuntimeException)
	{
        impl_checkDisposed_throw();

        Any aValue;
        switch ( getTypedControlWindow()->getOperationMode() )
        {
        case eMultiLineText:
            aValue <<= getTypedControlWindow()->GetTextValue();
            break;
        case eStringList:
            aValue <<= getTypedControlWindow()->GetStringListValue();
            break;
        }
        return aValue;
	}

	//------------------------------------------------------------------
    Type SAL_CALL OMultilineEditControl::getValueType() throw (RuntimeException)
    {
        if ( getTypedControlWindow()->getOperationMode() == eMultiLineText )
            return ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) );
        return ::getCppuType( static_cast< Sequence< ::rtl::OUString >* >( NULL ) );
    }

//............................................................................
} // namespace pcr
//............................................................................

ext: cxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice


text:
// Copyright (c) 2018 - The SmartCash Developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "proposaladdressdialog.h"
#include "ui_proposaladdressdialog.h"

#include "addresstablemodel.h"
#include "bitcoinunits.h"
#include "guiutil.h"
#include "optionsmodel.h"
#include "platformstyle.h"
#include "walletmodel.h"
#include "wallet/wallet.h"
#include "init.h"
#include "smartvoting/proposal.h"
#include "smartvoting/voting.h"
#include "messagesigner.h"
#include "util.h"
#include "validation.h"

#include <regex>

#include <boost/foreach.hpp>

#include <QMenu>
#include <QMessageBox>
#include <QSortFilterProxyModel>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QScrollBar>
#include <QDateTime>
#include <QApplication>
#include <QDialogButtonBox>
#include <QInputDialog>
#include <QFlags>
#include <QIcon>
#include <QSettings>
#include <QString>
#include <QRegularExpression>

bool ProposalAddressWidgetItem::operator<(const QTableWidgetItem &other) const {
    int column = other.column();

    if (column == ProposalAddressDialog::COLUMN_AMOUNT){
        QString t1 = text();
        QString t2 = other.text();

        t1 = t1.simplified();
        t1.replace( " ", "" );
        t1.replace("SMART", "");

        t2 = t2.simplified();
        t2.replace( " ", "" );
        t2.replace("SMART", "");

        return t1.toInt() < t2.toInt();

    }

    return QTableWidgetItem::operator<(other);
}

ProposalAddressDialog::ProposalAddressDialog(QWidget *parent) :
    QDialog(parent, Qt::WindowTitleHint),
    ui(new Ui::ProposalAddressDialog),
    strAddress(QString())
{
    ui->setupUi(this);

    QTableWidget *addressTable = ui->addressTable;

    addressTable->setAlternatingRowColors(true);
    addressTable->setSelectionBehavior(QAbstractItemView::SelectRows);
    addressTable->setSelectionMode(QAbstractItemView::SingleSelection);
    addressTable->setSortingEnabled(true);
    addressTable->setShowGrid(false);
    addressTable->verticalHeader()->hide();

    addressTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
    addressTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::Stretch);

    connect(ui->button, SIGNAL(clicked()), this, SLOT(close()));
    connect(ui->addressTable, SIGNAL(itemSelectionChanged()), this, SLOT(itemSelectionChanged()));

    ui->infoLabel->setText(ui->infoLabel->text().arg(CAmountToDouble(SMARTVOTING_PROPOSAL_FEE) + 0.1));

    this->setWindowTitle("Select the proposal address");

    updateUI();
}

ProposalAddressDialog::~ProposalAddressDialog()
{
    delete ui;
}

void ProposalAddressDialog::close()
{
    done(QDialog::Accepted);
}

void ProposalAddressDialog::updateUI()
{

    std::function<ProposalAddressWidgetItem * (QString)> createItem = [](QString title) {
        ProposalAddressWidgetItem * item = new ProposalAddressWidgetItem(title);
        return item;
    };

    LOCK2(cs_main, pwalletMain->cs_wallet);

    std::map<std::string,CAmount> mapAddresses;

    map<CTxDestination, CAmount> balances = pwalletMain->GetAddressBalances();

    BOOST_FOREACH(set<CTxDestination> grouping, pwalletMain->GetAddressGroupings())
    {
        BOOST_FOREACH(CTxDestination destination, grouping)
        {

            std::string address = CBitcoinAddress(destination).ToString();

            CAmount& nSum = mapAddresses[address];

            CAmount nAmount = balances[destination];

            nSum += nAmount;

        }
    }

    int nRow = 0;

    QTableWidget *table = ui->addressTable;

    table->clearContents();
    table->setRowCount(0);

    table->setSortingEnabled(false);

    for( auto address : mapAddresses ){

        if( address.second < SMARTVOTING_PROPOSAL_FEE + ( 0.1 * COIN ) )
            continue;

        table->insertRow(nRow);

        table->setItem(nRow, COLUMN_ADDRESS, createItem(QString::fromStdString(address.first)));

        QString amountString = QString::number(CAmountToDouble(address.second),'f',0);

        AddThousandsSpaces(amountString);

        table->setItem(nRow, COLUMN_AMOUNT, createItem(amountString + " SMART"));

        nRow++;
    }

    table->setSortingEnabled(true);
}

void ProposalAddressDialog::itemSelectionChanged()
{
    int nSelectedRow = ui->addressTable->currentRow();
    strAddress = ui->addressTable->item(nSelectedRow, COLUMN_ADDRESS)->text();
}

ext: cpp

max_stars_repo_name: trappist/Core-Smart

max_issues_repo_name: trappist/Core-Smart

max_forks_repo_name: trappist/Core-Smart


text:
// ---------------------------------------------------------------------------|
// Yuma Test Harness includes
// ---------------------------------------------------------------------------|
#include "test/support/misc-util/cpp-unit-op-formatter.h"

// ---------------------------------------------------------------------------|
// Boost test include files.
// ---------------------------------------------------------------------------|
#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/results_collector.hpp>

// ---------------------------------------------------------------------------|
// Standard includes
// ---------------------------------------------------------------------------|
#include <iostream>

// ---------------------------------------------------------------------------|
// File wide namespace use
// ---------------------------------------------------------------------------|
using namespace std;
using namespace boost::unit_test;

// ---------------------------------------------------------------------------|
// Anonymous namespace
// ---------------------------------------------------------------------------|
namespace {

class CppUnitSuiteVisitor : public test_tree_visitor
{
public:
    explicit CppUnitSuiteVisitor( const string& name ) : name_( name )
    {}

    virtual void visit( const test_case& tu )
    {
        const test_results& tr = results_collector.results( tu.p_id );
        cout << name_ << "::" << tu.p_name << " : " << ( tr.passed() ? "OK\n" : "FAIL\n" );
    }
private:
    string name_;
};

} // anonymous namesapce

// ---------------------------------------------------------------------------|
namespace YumaTest
{

// ---------------------------------------------------------------------------|
void CppUnitOpFormatter::do_confirmation_report(
        test_unit const& tu, std::ostream& ostr )
{
    using boost::unit_test::output::plain_report_formatter;

    CppUnitSuiteVisitor visitor( tu.p_name );
    traverse_test_tree( tu, visitor );

    const test_results& tr = results_collector.results( tu.p_id );
    if( tr.passed() )
    {
        ostr << "Test Passed\n";
    }
    else
    {
        plain_report_formatter::do_confirmation_report( tu, ostr );
    }
}

} // namespace YumaTest


text:
/*
 * This file is a part of the TChecker project.
 *
 * See files AUTHORS and LICENSE for copyright details.
 *
 */

#ifndef TCHECKER_VARIABLES_ACCESS_HH
#define TCHECKER_VARIABLES_ACCESS_HH

#include <tuple>

#include <boost/container/flat_map.hpp>
#include <boost/container/flat_set.hpp>

#include "tchecker/basictypes.hh"
#include "tchecker/utils/iterator.hh"

/*!
 \file access.hh
 \brief Variable access map
 */

namespace tchecker {

/*!
 \brief Type of variable access
 */
enum variable_access_t {
  VACCESS_READ,
  VACCESS_WRITE,
  VACCESS_ANY,
};

/*!
 \brief Type of variable
 */
enum variable_type_t {
  VTYPE_CLOCK,
  VTYPE_INTVAR,
};

/*!
 \class variable_access_map_t
 \brief Access maps from processes to variables and, conversely, variables to processes
 */
class variable_access_map_t {
  using v2p_key_t = std::tuple<tchecker::variable_id_t, enum tchecker::variable_type_t, enum tchecker::variable_access_t>;
  using p2v_key_t = std::tuple<tchecker::process_id_t, enum tchecker::variable_type_t, enum tchecker::variable_access_t>;
  using pid_set_t = boost::container::flat_set<tchecker::process_id_t>;
  using vid_set_t = boost::container::flat_set<tchecker::variable_id_t>;
  using v2p_map_t = boost::container::flat_map<v2p_key_t, pid_set_t>;
  using p2v_map_t = boost::container::flat_map<p2v_key_t, vid_set_t>;

public:
  /*!
   \brief Clear
   \post this map is empty
   */
  void clear();

  /*!
   \brief Add a variable access
   \param vid : variable identifier
   \param vtype : variable type
   \param vaccess : variable access
   \param pid : process identifier
   \pre vaccess is either READ or WRITE, and vtype is either CLOCK or INTVAR
   \post Accesss of type `vaccess` and tchecker::ANY, to variable `vid` of type `vtype`, by process `pid` have been added
   \throw std::invalid_argument : if the precondition is violated
   */
  void add(tchecker::variable_id_t vid, enum tchecker::variable_type_t vtype, enum tchecker::variable_access_t vaccess,
           tchecker::process_id_t pid);

  /*!
   \brief Accessor
   \return true if there is a shared variable in the map (i.e. a variable accessed by at least 2 processes), false otherwise
   */
  bool has_shared_variable() const;

  /*!
   \brief Type of iterator over process identifiers
   */
  using process_id_iterator_t = pid_set_t::const_iterator;

  /*!
   \brief Accessor
   \param vid : variable identifier
   \param vtype : type of variable
   \param vaccess : variable access
   \return the range of identifiers of the processes that perform an access of type `vaccess` on variable `vid` of type `vtype`
   */
  tchecker::range_t<process_id_iterator_t> accessing_processes(tchecker::variable_id_t vid,
                                                               enum tchecker::variable_type_t vtype,
                                                               enum tchecker::variable_access_t vaccess) const;

  /*!
   \brief Accessor
   \param vid : variable identifier
   \param vtype : type of variable
   \param vaccess : variable access
   \pre there is exactly one process that perform an access of type `vaccess` on variable `vid` of type `vtype`
   \return identifier of the process that perform an access of type `vaccess` on variable `vid` of type `vtype`
   \throw std::invalid_argument : if the precondition is violated
   */
  process_id_t accessing_process(tchecker::variable_id_t vid, enum tchecker::variable_type_t vtype,
                                 enum tchecker::variable_access_t vaccess) const;

  /*!
   \brief Type of iterator over variable identifiers
   */
  using variable_id_iterator_t = vid_set_t::const_iterator;

  /*!
   \brief Accessor
   \param pid : process identifier
   \param vtype : type of variable
   \param vaccess : variable access
   \retyrn the range of identifiers of the variables of type `vtype` that are accessed by process `pid`, with an access of type
   `vaccess`
   */
  tchecker::range_t<variable_id_iterator_t> accessed_variables(tchecker::process_id_t pid, enum tchecker::variable_type_t vtype,
                                                               enum tchecker::variable_access_t vaccess) const;

private:
  v2p_map_t _v2p_map;       /*!< Map : variable ID -> accessing process IDs */
  p2v_map_t _p2v_map;       /*!< Map : process ID -> accessed variable IDs */
  pid_set_t _empty_pid_set; /*!< Empty process ID set */
  vid_set_t _empty_vid_set; /*!< Empty variable ID set */
};

} // end of namespace tchecker

#endif // TCHECKER_VARIABLES_ACCESS_HH

ext: hh

max_stars_repo_name: arnabSur/tchecker

max_issues_repo_name: arnabSur/tchecker

max_forks_repo_name: arnabSur/tchecker


text:
/**
 *    Copyright (C) 2015 MongoDB Inc.
 *
 *    This program is free software: you can redistribute it and/or  modify
 *    it under the terms of the GNU Affero General Public License, version 3,
 *    as published by the Free Software Foundation.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the GNU Affero General Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kSharding

#include "mongo/platform/basic.h"

#include "mongo/s/chunk_manager.h"

#include <boost/next_prior.hpp>
#include <map>
#include <set>

#include "mongo/bson/util/bson_extract.h"
#include "mongo/client/remote_command_targeter.h"
#include "mongo/db/commands.h"
#include "mongo/db/matcher/extensions_callback_noop.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/query/index_bounds_builder.h"
#include "mongo/db/query/query_planner.h"
#include "mongo/db/query/query_planner_common.h"
#include "mongo/s/catalog/catalog_cache.h"
#include "mongo/s/catalog/catalog_manager.h"
#include "mongo/s/catalog/type_chunk.h"
#include "mongo/s/catalog/type_collection.h"
#include "mongo/s/chunk.h"
#include "mongo/s/chunk_diff.h"
#include "mongo/s/client/shard_connection.h"
#include "mongo/s/client/shard_registry.h"
#include "mongo/s/config.h"
#include "mongo/s/grid.h"
#include "mongo/util/log.h"
#include "mongo/util/timer.h"

namespace mongo {

using std::make_pair;
using std::map;
using std::max;
using std::pair;
using std::set;
using std::shared_ptr;
using std::string;
using std::unique_ptr;
using std::vector;

namespace {

/**
 * This is an adapter so we can use config diffs - mongos and mongod do them slightly
 * differently
 *
 * The mongos adapter here tracks all shards, and stores ranges by (max, Chunk) in the map.
 */
class CMConfigDiffTracker : public ConfigDiffTracker<shared_ptr<Chunk>> {
public:
    CMConfigDiffTracker(ChunkManager* manager) : _manager(manager) {}

    bool isTracked(const ChunkType& chunk) const final {
        // Mongos tracks all shards
        return true;
    }

    bool isMinKeyIndexed() const final {
        return false;
    }

    pair<BSONObj, shared_ptr<Chunk>> rangeFor(OperationContext* txn,
                                              const ChunkType& chunk) const final {
        shared_ptr<Chunk> c(new Chunk(txn, _manager, chunk));
        return make_pair(chunk.getMax(), c);
    }

    string shardFor(OperationContext* txn, const string& hostName) const final {
        const auto shard = grid.shardRegistry()->getShard(txn, hostName);
        uassert(ErrorCodes::ShardNotFound,
                str::stream() << "Shard " << hostName << " not found.",
                shard);
        return shard->getId();
    }

private:
    ChunkManager* const _manager;
};

bool allOfType(BSONType type, const BSONObj& o) {
    BSONObjIterator it(o);
    while (it.more()) {
        if (it.next().type() != type) {
            return false;
        }
    }
    return true;
}

bool isChunkMapValid(const ChunkMap& chunkMap) {
#define ENSURE(x)                                          \
    do {                                                   \
        if (!(x)) {                                        \
            log() << "ChunkManager::_isValid failed: " #x; \
            return false;                                  \
        }                                                  \
    } while (0)

    if (chunkMap.empty()) {
        return true;
    }

    // Check endpoints
    ENSURE(allOfType(MinKey, chunkMap.begin()->second->getMin()));
    ENSURE(allOfType(MaxKey, boost::prior(chunkMap.end())->second->getMax()));

    // Make sure there are no gaps or overlaps
    for (ChunkMap::const_iterator it = boost::next(chunkMap.begin()), end = chunkMap.end();
         it != end;
         ++it) {
        ChunkMap::const_iterator last = boost::prior(it);

        if (!(it->second->getMin() == last->second->getMax())) {
            log() << last->second->toString();
            log() << it->second->toString();
            log() << it->second->getMin();
            log() << last->second->getMax();
        }

        ENSURE(it->second->getMin() == last->second->getMax());
    }

    return true;

#undef ENSURE
}

}  // namespace

AtomicUInt32 ChunkManager::NextSequenceNumber(1U);

ChunkManager::ChunkManager(const string& ns, const ShardKeyPattern& pattern, bool unique)
    : _ns(ns),
      _keyPattern(pattern.getKeyPattern()),
      _unique(unique),
      _sequenceNumber(NextSequenceNumber.addAndFetch(1)),
      _chunkRanges() {}

ChunkManager::ChunkManager(const CollectionType& coll)
    : _ns(coll.getNs().ns()),
      _keyPattern(coll.getKeyPattern()),
      _unique(coll.getUnique()),
      _sequenceNumber(NextSequenceNumber.addAndFetch(1)),
      _chunkRanges() {
    // coll does not have correct version. Use same initial version as _load and createFirstChunks.
    _version = ChunkVersion(0, 0, coll.getEpoch());
}

void ChunkManager::loadExistingRanges(OperationContext* txn, const ChunkManager* oldManager) {
    int tries = 3;

    while (tries--) {
        ChunkMap chunkMap;
        set<ShardId> shardIds;
        ShardVersionMap shardVersions;

        Timer t;

        log() << "ChunkManager loading chunks for " << _ns << " sequenceNumber: " << _sequenceNumber
              << " based on: " << (oldManager ? oldManager->getVersion().toString() : "(empty)");

        bool success = _load(txn, chunkMap, shardIds, &shardVersions, oldManager);
        if (success) {
            // TODO: Merge into diff code above, so we validate in one place
            if (isChunkMapValid(chunkMap)) {
                _chunkMap.swap(chunkMap);
                _shardIds.swap(shardIds);
                _shardVersions.swap(shardVersions);
                _chunkRanges.reloadAll(_chunkMap);

                log() << "ChunkManager load took " << t.millis() << " ms and found version "
                      << _version;

                return;
            }
        }

        warning() << "ChunkManager load failed after " << t.millis()
                  << " ms and will be retried up to " << tries << " more times";

        sleepmillis(10 * (3 - tries));
    }

    // This will abort construction so we should never have a reference to an invalid config
    msgasserted(13282,
                str::stream() << "Couldn't load a valid config for " << _ns
                              << " after 3 attempts. Please try again.");
}

bool ChunkManager::_load(OperationContext* txn,
                         ChunkMap& chunkMap,
                         set<ShardId>& shardIds,
                         ShardVersionMap* shardVersions,
                         const ChunkManager* oldManager) {
    // Reset the max version, but not the epoch, when we aren't loading from the oldManager
    _version = ChunkVersion(0, 0, _version.epoch());

    // If we have a previous version of the ChunkManager to work from, use that info to reduce
    // our config query
    if (oldManager && oldManager->getVersion().isSet()) {
        // Get the old max version
        _version = oldManager->getVersion();

        // Load a copy of the old versions
        *shardVersions = oldManager->_shardVersions;

        // Load a copy of the chunk map, replacing the chunk manager with our own
        const ChunkMap& oldChunkMap = oldManager->getChunkMap();

        // Could be v.expensive
        // TODO: If chunks were immutable and didn't reference the manager, we could do more
        // interesting things here
        for (const auto& oldChunkMapEntry : oldChunkMap) {
            shared_ptr<Chunk> oldC = oldChunkMapEntry.second;
            shared_ptr<Chunk> newC(new Chunk(
                this, oldC->getMin(), oldC->getMax(), oldC->getShardId(), oldC->getLastmod()));

            newC->setBytesWritten(oldC->getBytesWritten());

            chunkMap.insert(make_pair(oldC->getMax(), newC));
        }

        LOG(2) << "loading chunk manager for collection " << _ns
               << " using old chunk manager w/ version " << _version.toString() << " and "
               << oldChunkMap.size() << " chunks";
    }

    // Attach a diff tracker for the versioned chunk data
    CMConfigDiffTracker differ(this);
    differ.attach(_ns, chunkMap, _version, *shardVersions);

    // Diff tracker should *always* find at least one chunk if collection exists
    // Get the diff query required
    auto diffQuery = differ.configDiffQuery();

    repl::OpTime opTime;
    std::vector<ChunkType> chunks;
    uassertStatusOK(grid.catalogManager(txn)->getChunks(
        txn, diffQuery.query, diffQuery.sort, boost::none, &chunks, &opTime));

    invariant(opTime >= _configOpTime);
    _configOpTime = opTime;

    int diffsApplied = differ.calculateConfigDiff(txn, chunks);
    if (diffsApplied > 0) {
        LOG(2) << "loaded " << diffsApplied << " chunks into new chunk manager for " << _ns
               << " with version " << _version;

        // Add all existing shards we find to the shards set
        for (ShardVersionMap::iterator it = shardVersions->begin(); it != shardVersions->end();) {
            shared_ptr<Shard> shard = grid.shardRegistry()->getShard(txn, it->first);
            if (shard) {
                shardIds.insert(it->first);
                ++it;
            } else {
                shardVersions->erase(it++);
            }
        }

        _configOpTime = opTime;

        return true;
    } else if (diffsApplied == 0) {
        // No chunks were found for the ns
        warning() << "no chunks found when reloading " << _ns << ", previous version was "
                  << _version;

        // Set all our data to empty
        chunkMap.clear();
        shardVersions->clear();

        _version = ChunkVersion(0, 0, OID());
        _configOpTime = opTime;

        return true;
    } else {  // diffsApplied < 0

        bool allInconsistent = (differ.numValidDiffs() == 0);
        if (allInconsistent) {
            // All versions are different, this can be normal
            warning() << "major change in chunk information found when reloading " << _ns
                      << ", previous version was " << _version;
        } else {
            // Inconsistent load halfway through (due to yielding cursor during load)
            // should be rare
            warning() << "inconsistent chunks found when reloading " << _ns
                      << ", previous version was " << _version << ", this should be rare";
        }

        // Set all our data to empty to be extra safe
        chunkMap.clear();
        shardVersions->clear();

        _version = ChunkVersion(0, 0, OID());

        return allInconsistent;
    }
}

shared_ptr<ChunkManager> ChunkManager::reload(OperationContext* txn, bool force) const {
    const NamespaceString nss(_ns);
    auto config = uassertStatusOK(grid.catalogCache()->getDatabase(txn, nss.db().toString()));

    return config->getChunkManagerIfExists(txn, getns(), force);
}

void ChunkManager::_printChunks() const {
    for (ChunkMap::const_iterator it = _chunkMap.begin(), end = _chunkMap.end(); it != end; ++it) {
        log() << *it->second;
    }
}

void ChunkManager::calcInitSplitsAndShards(OperationContext* txn,
                                           const ShardId& primaryShardId,
                                           const vector<BSONObj>* initPoints,
                                           const set<ShardId>* initShardIds,
                                           vector<BSONObj>* splitPoints,
                                           vector<ShardId>* shardIds) const {
    verify(_chunkMap.size() == 0);

    Chunk c(this,
            _keyPattern.getKeyPattern().globalMin(),
            _keyPattern.getKeyPattern().globalMax(),
            primaryShardId);

    if (!initPoints || !initPoints->size()) {
        // discover split points
        const auto primaryShard = grid.shardRegistry()->getShard(txn, primaryShardId);
        const NamespaceString nss{getns()};
        auto result = grid.shardRegistry()->runIdempotentCommandOnShard(
            txn,
            primaryShard,
            ReadPreferenceSetting{ReadPreference::PrimaryPreferred},
            nss.db().toString(),
            BSON("count" << nss.coll()));

        long long numObjects = 0;
        uassertStatusOK(result.getStatus());
        uassertStatusOK(Command::getStatusFromCommandResult(result.getValue()));
        uassertStatusOK(bsonExtractIntegerField(result.getValue(), "n", &numObjects));

        if (numObjects > 0)
            c.pickSplitVector(txn, *splitPoints, Chunk::MaxChunkSize);

        // since docs already exists, must use primary shard
        shardIds->push_back(primaryShardId);
    } else {
        // make sure points are unique and ordered
        set<BSONObj> orderedPts;
        for (unsigned i = 0; i < initPoints->size(); ++i) {
            BSONObj pt = (*initPoints)[i];
            orderedPts.insert(pt);
        }
        for (set<BSONObj>::iterator it = orderedPts.begin(); it != orderedPts.end(); ++it) {
            splitPoints->push_back(*it);
        }

        if (!initShardIds || !initShardIds->size()) {
            // If not specified, only use the primary shard (note that it's not safe for mongos
            // to put initial chunks on other shards without the primary mongod knowing).
            shardIds->push_back(primaryShardId);
        } else {
            std::copy(initShardIds->begin(), initShardIds->end(), std::back_inserter(*shardIds));
        }
    }
}

Status ChunkManager::createFirstChunks(OperationContext* txn,
                                       const ShardId& primaryShardId,
                                       const vector<BSONObj>* initPoints,
                                       const set<ShardId>* initShardIds) {
    // TODO distlock?
    // TODO: Race condition if we shard the collection and insert data while we split across
    // the non-primary shard.

    vector<BSONObj> splitPoints;
    vector<ShardId> shardIds;
    calcInitSplitsAndShards(txn, primaryShardId, initPoints, initShardIds, &splitPoints, &shardIds);

    // this is the first chunk; start the versioning from scratch
    ChunkVersion version(1, 0, OID::gen());

    log() << "going to create " << splitPoints.size() + 1 << " chunk(s) for: " << _ns
          << " using new epoch " << version.epoch();

    for (unsigned i = 0; i <= splitPoints.size(); i++) {
        BSONObj min = i == 0 ? _keyPattern.getKeyPattern().globalMin() : splitPoints[i - 1];
        BSONObj max =
            i < splitPoints.size() ? splitPoints[i] : _keyPattern.getKeyPattern().globalMax();

        ChunkType chunk;
        chunk.setName(Chunk::genID(_ns, min));
        chunk.setNS(_ns);
        chunk.setMin(min);
        chunk.setMax(max);
        chunk.setShard(shardIds[i % shardIds.size()]);
        chunk.setVersion(version);

        Status status = grid.catalogManager(txn)
                            ->insertConfigDocument(txn, ChunkType::ConfigNS, chunk.toBSON());
        if (!status.isOK()) {
            const string errMsg = str::stream()
                << "Creating first chunks failed: " << status.reason();
            error() << errMsg;
            return Status(status.code(), errMsg);
        }

        version.incMinor();
    }

    _version = ChunkVersion(0, 0, version.epoch());

    return Status::OK();
}

ChunkPtr ChunkManager::findIntersectingChunk(OperationContext* txn, const BSONObj& shardKey) const {
    {
        BSONObj chunkMin;
        ChunkPtr chunk;
        {
            ChunkMap::const_iterator it = _chunkMap.upper_bound(shardKey);
            if (it != _chunkMap.end()) {
                chunkMin = it->first;
                chunk = it->second;
            }
        }

        if (chunk) {
            if (chunk->containsKey(shardKey)) {
                return chunk;
            }

            log() << chunkMin;
            log() << *chunk;
            log() << shardKey;

            reload(txn);
            msgasserted(13141, "Chunk map pointed to incorrect chunk");
        }
    }

    msgasserted(8070,
                str::stream() << "couldn't find a chunk intersecting: " << shardKey
                              << " for ns: " << _ns << " at version: " << _version.toString()
                              << ", number of chunks: " << _chunkMap.size());
}

void ChunkManager::getShardIdsForQuery(OperationContext* txn,
                                       const BSONObj& query,
                                       set<ShardId>* shardIds) const {
    auto statusWithCQ =
        CanonicalQuery::canonicalize(NamespaceString(_ns), query, ExtensionsCallbackNoop());

    uassertStatusOK(statusWithCQ.getStatus());
    unique_ptr<CanonicalQuery> cq = std::move(statusWithCQ.getValue());

    // Query validation
    if (QueryPlannerCommon::hasNode(cq->root(), MatchExpression::GEO_NEAR)) {
        uassert(13501, "use geoNear command rather than $near query", false);
    }

    // Fast path for targeting equalities on the shard key.
    auto shardKeyToFind = _keyPattern.extractShardKeyFromQuery(*cq);
    if (shardKeyToFind.isOK() && !shardKeyToFind.getValue().isEmpty()) {
        auto chunk = findIntersectingChunk(txn, shardKeyToFind.getValue());
        shardIds->insert(chunk->getShardId());
        return;
    }

    // Transforms query into bounds for each field in the shard key
    // for example :
    //   Key { a: 1, b: 1 },
    //   Query { a : { $gte : 1, $lt : 2 },
    //            b : { $gte : 3, $lt : 4 } }
    //   => Bounds { a : [1, 2), b : [3, 4) }
    IndexBounds bounds = getIndexBoundsForQuery(_keyPattern.toBSON(), *cq);

    // Transforms bounds for each shard key field into full shard key ranges
    // for example :
    //   Key { a : 1, b : 1 }
    //   Bounds { a : [1, 2), b : [3, 4) }
    //   => Ranges { a : 1, b : 3 } => { a : 2, b : 4 }
    BoundList ranges = _keyPattern.flattenBounds(bounds);

    for (BoundList::const_iterator it = ranges.begin(); it != ranges.end(); ++it) {
        getShardIdsForRange(*shardIds, it->first /*min*/, it->second /*max*/);

        // once we know we need to visit all shards no need to keep looping
        if (shardIds->size() == _shardIds.size())
            break;
    }

    // SERVER-4914 Some clients of getShardIdsForQuery() assume at least one shard will be
    // returned.  For now, we satisfy that assumption by adding a shard with no matches rather
    // than return an empty set of shards.
    if (shardIds->empty()) {
        massert(16068, "no chunk ranges available", !_chunkRanges.ranges().empty());
        shardIds->insert(_chunkRanges.ranges().begin()->second->getShardId());
    }
}

void ChunkManager::getShardIdsForRange(set<ShardId>& shardIds,
                                       const BSONObj& min,
                                       const BSONObj& max) const {
    ChunkRangeMap::const_iterator it = _chunkRanges.upper_bound(min);
    ChunkRangeMap::const_iterator end = _chunkRanges.upper_bound(max);

    massert(13507,
            str::stream() << "no chunks found between bounds " << min << " and " << max,
            it != _chunkRanges.ranges().end());

    if (end != _chunkRanges.ranges().end())
        ++end;

    for (; it != end; ++it) {
        shardIds.insert(it->second->getShardId());

        // once we know we need to visit all shards no need to keep looping
        if (shardIds.size() == _shardIds.size())
            break;
    }
}

void ChunkManager::getAllShardIds(set<ShardId>* all) const {
    dassert(all);

    all->insert(_shardIds.begin(), _shardIds.end());
}

IndexBounds ChunkManager::getIndexBoundsForQuery(const BSONObj& key,
                                                 const CanonicalQuery& canonicalQuery) {
    // TODO: special-casing TEXT here is no longer necessary.  The work to remove this special case
    // is being tracked at SERVER-21511.
    if (QueryPlannerCommon::hasNode(canonicalQuery.root(), MatchExpression::TEXT)) {
        IndexBounds bounds;
        IndexBoundsBuilder::allValuesBounds(key, &bounds);  // [minKey, maxKey]
        return bounds;
    }

    // Consider shard key as an index
    string accessMethod = IndexNames::findPluginName(key);
    dassert(accessMethod == IndexNames::BTREE || accessMethod == IndexNames::HASHED);

    // Use query framework to generate index bounds
    QueryPlannerParams plannerParams;
    // Must use "shard key" index
    plannerParams.options = QueryPlannerParams::NO_TABLE_SCAN;
    IndexEntry indexEntry(key,
                          accessMethod,
                          false /* multiKey */,
                          false /* sparse */,
                          false /* unique */,
                          "shardkey",
                          NULL /* filterExpr */,
                          BSONObj());
    plannerParams.indices.push_back(indexEntry);

    OwnedPointerVector<QuerySolution> solutions;
    Status status = QueryPlanner::plan(canonicalQuery, plannerParams, &solutions.mutableVector());
    uassert(status.code(), status.reason(), status.isOK());

    IndexBounds bounds;

    for (vector<QuerySolution*>::const_iterator it = solutions.begin();
         bounds.size() == 0 && it != solutions.end();
         it++) {
        // Try next solution if we failed to generate index bounds, i.e. bounds.size() == 0
        bounds = collapseQuerySolution((*it)->root.get());
    }

    if (bounds.size() == 0) {
        // We cannot plan the query without collection scan, so target to all shards.
        IndexBoundsBuilder::allValuesBounds(key, &bounds);  // [minKey, maxKey]
    }
    return bounds;
}

IndexBounds ChunkManager::collapseQuerySolution(const QuerySolutionNode* node) {
    if (node->children.size() == 0) {
        invariant(node->getType() == STAGE_IXSCAN);

        const IndexScanNode* ixNode = static_cast<const IndexScanNode*>(node);
        return ixNode->bounds;
    }

    if (node->children.size() == 1) {
        // e.g. FETCH -> IXSCAN
        return collapseQuerySolution(node->children.front());
    }

    // children.size() > 1, assert it's OR / SORT_MERGE.
    if (node->getType() != STAGE_OR && node->getType() != STAGE_SORT_MERGE) {
        // Unexpected node. We should never reach here.
        error() << "could not generate index bounds on query solution tree: " << node->toString();
        dassert(false);  // We'd like to know this error in testing.

        // Bail out with all shards in production, since this isn't a fatal error.
        return IndexBounds();
    }

    IndexBounds bounds;
    for (vector<QuerySolutionNode*>::const_iterator it = node->children.begin();
         it != node->children.end();
         it++) {
        // The first branch under OR
        if (it == node->children.begin()) {
            invariant(bounds.size() == 0);
            bounds = collapseQuerySolution(*it);
            if (bounds.size() == 0) {  // Got unexpected node in query solution tree
                return IndexBounds();
            }
            continue;
        }

        IndexBounds childBounds = collapseQuerySolution(*it);
        if (childBounds.size() == 0) {  // Got unexpected node in query solution tree
            return IndexBounds();
        }

        invariant(childBounds.size() == bounds.size());
        for (size_t i = 0; i < bounds.size(); i++) {
            bounds.fields[i].intervals.insert(bounds.fields[i].intervals.end(),
                                              childBounds.fields[i].intervals.begin(),
                                              childBounds.fields[i].intervals.end());
        }
    }

    for (size_t i = 0; i < bounds.size(); i++) {
        IndexBoundsBuilder::unionize(&bounds.fields[i]);
    }

    return bounds;
}

bool ChunkManager::compatibleWith(const ChunkManager& other, const string& shardName) const {
    // Return true if the shard version is the same in the two chunk managers
    // TODO: This doesn't need to be so strong, just major vs
    return other.getVersion(shardName).equals(getVersion(shardName));
}

ChunkVersion ChunkManager::getVersion(const std::string& shardName) const {
    ShardVersionMap::const_iterator i = _shardVersions.find(shardName);
    if (i == _shardVersions.end()) {
        // Shards without explicitly tracked shard versions (meaning they have
        // no chunks) always have a version of (0, 0, epoch).  Note this is
        // *different* from the dropped chunk version of (0, 0, OID(000...)).
        // See s/chunk_version.h.
        return ChunkVersion(0, 0, _version.epoch());
    }
    return i->second;
}

ChunkVersion ChunkManager::getVersion() const {
    return _version;
}

string ChunkManager::toString() const {
    StringBuilder sb;
    sb << "ChunkManager: " << _ns << " key:" << _keyPattern.toString() << '\n';

    for (ChunkMap::const_iterator i = _chunkMap.begin(); i != _chunkMap.end(); ++i) {
        sb << "\t" << i->second->toString() << '\n';
    }

    return sb.str();
}

ChunkRange::ChunkRange(ChunkMap::const_iterator begin, const ChunkMap::const_iterator end)
    : _manager(begin->second->getManager()),
      _shardId(begin->second->getShardId()),
      _min(begin->second->getMin()),
      _max(boost::prior(end)->second->getMax()) {
    invariant(begin != end);

    DEV while (begin != end) {
        dassert(begin->second->getManager() == _manager);
        dassert(begin->second->getShardId() == _shardId);
        ++begin;
    }
}

ChunkRange::ChunkRange(const ChunkRange& min, const ChunkRange& max)
    : _manager(min.getManager()),
      _shardId(min.getShardId()),
      _min(min.getMin()),
      _max(max.getMax()) {
    invariant(min.getShardId() == max.getShardId());
    invariant(min.getManager() == max.getManager());
    invariant(min.getMax() == max.getMin());
}

string ChunkRange::toString() const {
    StringBuilder sb;
    sb << "ChunkRange(min=" << _min << ", max=" << _max << ", shard=" << _shardId << ")";

    return sb.str();
}

void ChunkRangeManager::assertValid() const {
    if (_ranges.empty())
        return;

    try {
        // No Nulls
        for (ChunkRangeMap::const_iterator it = _ranges.begin(), end = _ranges.end(); it != end;
             ++it) {
            verify(it->second);
        }

        // Check endpoints
        verify(allOfType(MinKey, _ranges.begin()->second->getMin()));
        verify(allOfType(MaxKey, boost::prior(_ranges.end())->second->getMax()));

        // Make sure there are no gaps or overlaps
        for (ChunkRangeMap::const_iterator it = boost::next(_ranges.begin()), end = _ranges.end();
             it != end;
             ++it) {
            ChunkRangeMap::const_iterator last = boost::prior(it);
            verify(it->second->getMin() == last->second->getMax());
        }

        // Check Map keys
        for (ChunkRangeMap::const_iterator it = _ranges.begin(), end = _ranges.end(); it != end;
             ++it) {
            verify(it->first == it->second->getMax());
        }

        // Make sure we match the original chunks
        const ChunkMap chunks = _ranges.begin()->second->getManager()->_chunkMap;
        for (ChunkMap::const_iterator i = chunks.begin(); i != chunks.end(); ++i) {
            const ChunkPtr chunk = i->second;

            ChunkRangeMap::const_iterator min = _ranges.upper_bound(chunk->getMin());
            ChunkRangeMap::const_iterator max = _ranges.lower_bound(chunk->getMax());

            verify(min != _ranges.end());
            verify(max != _ranges.end());
            verify(min == max);
            verify(min->second->getShardId() == chunk->getShardId());
            verify(min->second->containsKey(chunk->getMin()));
            verify(min->second->containsKey(chunk->getMax()) ||
                   (min->second->getMax() == chunk->getMax()));
        }

    } catch (...) {
        error() << "\t invalid ChunkRangeMap! printing ranges:";

        for (ChunkRangeMap::const_iterator it = _ranges.begin(), end = _ranges.end(); it != end;
             ++it) {
            log() << it->first << ": " << it->second->toString();
        }

        throw;
    }
}

void ChunkRangeManager::reloadAll(const ChunkMap& chunks) {
    _ranges.clear();
    _insertRange(chunks.begin(), chunks.end());

    DEV assertValid();
}

void ChunkRangeManager::_insertRange(ChunkMap::const_iterator begin,
                                     const ChunkMap::const_iterator end) {
    while (begin != end) {
        ChunkMap::const_iterator first = begin;
        ShardId shardId = first->second->getShardId();
        while (begin != end && (begin->second->getShardId() == shardId))
            ++begin;

        shared_ptr<ChunkRange> cr(new ChunkRange(first, begin));
        _ranges[cr->getMax()] = cr;
    }
}

int ChunkManager::getCurrentDesiredChunkSize() const {
    // split faster in early chunks helps spread out an initial load better
    const int minChunkSize = 1 << 20;  // 1 MBytes

    int splitThreshold = Chunk::MaxChunkSize;

    int nc = numChunks();

    if (nc <= 1) {
        return 1024;
    } else if (nc < 3) {
        return minChunkSize / 2;
    } else if (nc < 10) {
        splitThreshold = max(splitThreshold / 4, minChunkSize);
    } else if (nc < 20) {
        splitThreshold = max(splitThreshold / 2, minChunkSize);
    }

    return splitThreshold;
}

repl::OpTime ChunkManager::getConfigOpTime() const {
    return _configOpTime;
}

}  // namespace mongo

max_stars_repo_name: bmhoang/mongodb

max_issues_repo_name: bmhoang/mongodb

max_forks_repo_name: bmhoang/mongodb


text: #include <boost/units/systems/si/angular_momentum.hpp>

ext: hpp

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino