<commit_before>/*************************************************************************
 *
 *  $RCSfile: Columns.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: fs $ $Date: 2002-12-02 09:56:27 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _FRM_COLUMNS_HXX
#define _FRM_COLUMNS_HXX

#ifndef _CPPUHELPER_COMPONENT_HXX_
#include <cppuhelper/component.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_AGGREGATION_HXX_
#include <comphelper/propagg.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#include "strings.hxx"

#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOBJECTOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XObjectOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOBJECTINPUTSTREAM_HPP_
#include <com/sun/star/io/XObjectInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef FORMS_COMPONENT_CLONEABLE_HXX
#include "cloneable.hxx"
#endif

using namespace comphelper;

//.........................................................................
namespace frm
{
//.........................................................................

//==================================================================
// OGridColumn
//==================================================================
typedef ::cppu::WeakAggComponentImplHelper2<    ::com::sun::star::container::XChild,
                                                ::com::sun::star::lang::XUnoTunnel > OGridColumn_BASE;
class OGridColumn   :public ::comphelper::OBaseMutex
                    ,public OGridColumn_BASE
                    ,public OPropertySetAggregationHelper
                    ,public OCloneableAggregation
{
protected:
// [properties]
    ::com::sun::star::uno::Any  m_aWidth;                   // column width
    ::com::sun::star::uno::Any  m_aAlign;                   // column alignment
    ::com::sun::star::uno::Any  m_aHidden;                  // column hidden?
// [properties]

    InterfaceRef                m_xParent;
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation>
                                m_xAggregate;
    ::rtl::OUString             m_aModelName;

// [properties]
    ::rtl::OUString             m_aLabel;                   // Name der Spalte
// [properties]

public:
    OGridColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _sModelName = ::rtl::OUString());
    OGridColumn(const OGridColumn* _pOriginal, const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory );
    virtual ~OGridColumn();

    // UNO Anbindung
    DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OGridColumn_BASE);
    virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException);

    static const ::com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelImplementationId();
    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence<sal_Int8>& _rIdentifier) throw(::com::sun::star::uno::RuntimeException);

// XTypeProvider
    virtual ::com::sun::star::uno::Sequence<sal_Int8>           SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type>   SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException);

// OComponentHelper
    virtual void SAL_CALL disposing();

// ::com::sun::star::lang::XEventListener
    virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

// ::com::sun::star::container::XChild
    virtual InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException){return m_xParent;}
    virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);

// ::com::sun::star::io::XPersistObject
    virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream);
    virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream);

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException);
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
    virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
    virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                          sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                        throw(::com::sun::star::lang::IllegalArgumentException);
    virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception);

// ::com::sun::star::beans::XPropertyState
    virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle);
    virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle);
    virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const;

    const ::rtl::OUString& getModelName() const { return m_aModelName; }

protected:
    static void clearAggregateProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps, sal_Bool bAllowDropDown);
    static void setOwnProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps);

    DECLARE_XCLONEABLE();
};

#define DECL_COLUMN(ClassName)                                      \
class ClassName                                                     \
    :public OGridColumn                                             \
    ,public OAggregationArrayUsageHelper< ClassName >               \
{                                                                                \
public:                                                                             \
    ClassName(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);\
                                                                                \
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException);  \
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();             \
    \
    virtual void fillProperties(    \
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps,  \
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps  \
        ) const;    \
};

#define IMPL_COLUMN(ClassName, Model, bAllowDropDown)                               \
ClassName::ClassName(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory) \
    :OGridColumn(_rxFactory, Model){}                                           \
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  ClassName::getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException)\
{                                                                                \
    ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  xInfo( createPropertySetInfo( getInfoHelper() ) );    \
    return xInfo;                                                                   \
}                                                                                \
::cppu::IPropertyArrayHelper& ClassName::getInfoHelper()                \
{                                                                                \
    return *const_cast<ClassName*>(this)->getArrayHelper(); \
}   \
void ClassName::fillProperties( \
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps,  \
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps  \
    ) const \
{   \
    if (m_xAggregateSet.is())   \
    {   \
        _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties();  \
        clearAggregateProperties(_rAggregateProps, bAllowDropDown);                 \
        setOwnProperties(_rProps);                                              \
    }   \
}   \

// liste der moeglichen Controls
DECLARE_CONSTASCII_USTRING(FRM_COL_TEXTFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_CHECKBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_COMBOBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_LISTBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_NUMERICFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_DATEFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_TIMEFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_CURRENCYFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_PATTERNFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_FORMATTEDFIELD);

// column type ids
#define TYPE_CHECKBOX       0
#define TYPE_COMBOBOX       1
#define TYPE_CURRENCYFIELD  2
#define TYPE_DATEFIELD      3
#define TYPE_FORMATTEDFIELD 4
#define TYPE_LISTBOX        5
#define TYPE_NUMERICFIELD   6
#define TYPE_PATTERNFIELD   7
#define TYPE_TEXTFIELD      8
#define TYPE_TIMEFIELD      9

// liste aller bekannten columns
const StringSequence& getColumnTypes();
sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName);

// Columns
DECL_COLUMN(TextFieldColumn)
DECL_COLUMN(PatternFieldColumn)
DECL_COLUMN(DateFieldColumn)
DECL_COLUMN(TimeFieldColumn)
DECL_COLUMN(NumericFieldColumn)
DECL_COLUMN(CurrencyFieldColumn)
DECL_COLUMN(CheckBoxColumn)
DECL_COLUMN(ComboBoxColumn)
DECL_COLUMN(ListBoxColumn)
DECL_COLUMN(FormattedFieldColumn)

#endif // _FRM_COLUMNS_HXX

//.........................................................................
}   // namespace frm
//.........................................................................

<commit_msg>INTEGRATION: CWS formcelllinkage (1.5.92); FILE MERGED 2003/10/01 09:18:18 fs 1.5.92.1: #i18994# merging the changes from the CWS fs002<commit_after>/*************************************************************************
 *
 *  $RCSfile: Columns.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: obo $ $Date: 2003-10-21 08:55:24 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _FRM_COLUMNS_HXX
#define _FRM_COLUMNS_HXX

#ifndef _CPPUHELPER_COMPONENT_HXX_
#include <cppuhelper/component.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_ARRAY_HELPER_HXX_
#include <comphelper/proparrhlp.hxx>
#endif
#ifndef _COMPHELPER_PROPERTY_AGGREGATION_HXX_
#include <comphelper/propagg.hxx>
#endif
#ifndef _COMPHELPER_UNO3_HXX_
#include <comphelper/uno3.hxx>
#endif
#include "strings.hxx"

#ifndef _COM_SUN_STAR_CONTAINER_XCHILD_HPP_
#include <com/sun/star/container/XChild.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOBJECTOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XObjectOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOBJECTINPUTSTREAM_HPP_
#include <com/sun/star/io/XObjectInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_LANG_XUNOTUNNEL_HPP_
#include <com/sun/star/lang/XUnoTunnel.hpp>
#endif
#ifndef _CPPUHELPER_COMPBASE2_HXX_
#include <cppuhelper/compbase2.hxx>
#endif
#ifndef _COMPHELPER_BROADCASTHELPER_HXX_
#include <comphelper/broadcasthelper.hxx>
#endif
#ifndef FORMS_COMPONENT_CLONEABLE_HXX
#include "cloneable.hxx"
#endif

using namespace comphelper;

//.........................................................................
namespace frm
{
//.........................................................................

//==================================================================
// OGridColumn
//==================================================================
typedef ::cppu::WeakAggComponentImplHelper2<    ::com::sun::star::container::XChild,
                                                ::com::sun::star::lang::XUnoTunnel > OGridColumn_BASE;
class OGridColumn   :public ::comphelper::OBaseMutex
                    ,public OGridColumn_BASE
                    ,public OPropertySetAggregationHelper
                    ,public OCloneableAggregation
{
protected:
// [properties]
    ::com::sun::star::uno::Any  m_aWidth;                   // column width
    ::com::sun::star::uno::Any  m_aAlign;                   // column alignment
    ::com::sun::star::uno::Any  m_aHidden;                  // column hidden?
// [properties]

    InterfaceRef                m_xParent;
    ::com::sun::star::uno::Reference< ::com::sun::star::uno::XAggregation>
                                m_xAggregate;
    ::rtl::OUString             m_aModelName;

// [properties]
    ::rtl::OUString             m_aLabel;                   // Name der Spalte
// [properties]

public:
    OGridColumn(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory, const ::rtl::OUString& _sModelName = ::rtl::OUString());
    OGridColumn(const OGridColumn* _pOriginal, const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory );
    virtual ~OGridColumn();

    // UNO Anbindung
    DECLARE_UNO3_AGG_DEFAULTS(OGridControlModel, OGridColumn_BASE);
    virtual ::com::sun::star::uno::Any SAL_CALL queryAggregation( const ::com::sun::star::uno::Type& _rType ) throw (::com::sun::star::uno::RuntimeException);

    static const ::com::sun::star::uno::Sequence<sal_Int8>& getUnoTunnelImplementationId();
    // XUnoTunnel
    virtual sal_Int64 SAL_CALL getSomething( const ::com::sun::star::uno::Sequence<sal_Int8>& _rIdentifier) throw(::com::sun::star::uno::RuntimeException);

// XTypeProvider
    virtual ::com::sun::star::uno::Sequence<sal_Int8>           SAL_CALL getImplementationId() throw(::com::sun::star::uno::RuntimeException);
    virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type>   SAL_CALL getTypes() throw(::com::sun::star::uno::RuntimeException);

// OComponentHelper
    virtual void SAL_CALL disposing();

// ::com::sun::star::lang::XEventListener
    virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& _rSource) throw(::com::sun::star::uno::RuntimeException);

// ::com::sun::star::container::XChild
    virtual InterfaceRef SAL_CALL getParent() throw(::com::sun::star::uno::RuntimeException){return m_xParent;}
    virtual void SAL_CALL setParent(const InterfaceRef& Parent) throw(::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException);

// ::com::sun::star::io::XPersistObject
    virtual void SAL_CALL write(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectOutputStream>& _rxOutStream);
    virtual void SAL_CALL read(const ::com::sun::star::uno::Reference< ::com::sun::star::io::XObjectInputStream>& _rxInStream);

// ::com::sun::star::beans::XPropertySet
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException);
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
    virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle ) const;
    virtual sal_Bool SAL_CALL convertFastPropertyValue(::com::sun::star::uno::Any& rConvertedValue, ::com::sun::star::uno::Any& rOldValue,
                                          sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue )
                                        throw(::com::sun::star::lang::IllegalArgumentException);
    virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 nHandle, const ::com::sun::star::uno::Any& rValue) throw (::com::sun::star::uno::Exception);

// ::com::sun::star::beans::XPropertyState
    virtual ::com::sun::star::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle);
    virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle);
    virtual ::com::sun::star::uno::Any getPropertyDefaultByHandle( sal_Int32 nHandle ) const;

    const ::rtl::OUString& getModelName() const { return m_aModelName; }

protected:
    static void clearAggregateProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps, sal_Bool bAllowDropDown);
    static void setOwnProperties(::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property>& seqProps);
};

#define DECL_COLUMN(ClassName)                                      \
class ClassName                                                     \
    :public OGridColumn                                             \
    ,public OAggregationArrayUsageHelper< ClassName >               \
{                                                                                \
public:                                                                             \
    ClassName(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory);\
                                                                                \
    virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo> SAL_CALL getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException);  \
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();             \
    \
    virtual void fillProperties(    \
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps,  \
        ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps  \
        ) const;    \
};

#define IMPL_COLUMN(ClassName, Model, bAllowDropDown)                               \
ClassName::ClassName(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory>& _rxFactory) \
    :OGridColumn(_rxFactory, Model){}                                           \
::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  ClassName::getPropertySetInfo() throw(::com::sun::star::uno::RuntimeException)\
{                                                                                \
    ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo>  xInfo( createPropertySetInfo( getInfoHelper() ) );    \
    return xInfo;                                                                   \
}                                                                                \
::cppu::IPropertyArrayHelper& ClassName::getInfoHelper()                \
{                                                                                \
    return *const_cast<ClassName*>(this)->getArrayHelper(); \
}   \
void ClassName::fillProperties( \
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rProps,  \
    ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >& /* [out] */ _rAggregateProps  \
    ) const \
{   \
    if (m_xAggregateSet.is())   \
    {   \
        _rAggregateProps = m_xAggregateSet->getPropertySetInfo()->getProperties();  \
        clearAggregateProperties(_rAggregateProps, bAllowDropDown);                 \
        setOwnProperties(_rProps);                                              \
    }   \
}   \

// liste der moeglichen Controls
DECLARE_CONSTASCII_USTRING(FRM_COL_TEXTFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_CHECKBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_COMBOBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_LISTBOX);
DECLARE_CONSTASCII_USTRING(FRM_COL_NUMERICFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_DATEFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_TIMEFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_CURRENCYFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_PATTERNFIELD);
DECLARE_CONSTASCII_USTRING(FRM_COL_FORMATTEDFIELD);

// column type ids
#define TYPE_CHECKBOX       0
#define TYPE_COMBOBOX       1
#define TYPE_CURRENCYFIELD  2
#define TYPE_DATEFIELD      3
#define TYPE_FORMATTEDFIELD 4
#define TYPE_LISTBOX        5
#define TYPE_NUMERICFIELD   6
#define TYPE_PATTERNFIELD   7
#define TYPE_TEXTFIELD      8
#define TYPE_TIMEFIELD      9

// liste aller bekannten columns
const StringSequence& getColumnTypes();
sal_Int32 getColumnTypeByModelName(const ::rtl::OUString& aModelName);

// Columns
DECL_COLUMN(TextFieldColumn)
DECL_COLUMN(PatternFieldColumn)
DECL_COLUMN(DateFieldColumn)
DECL_COLUMN(TimeFieldColumn)
DECL_COLUMN(NumericFieldColumn)
DECL_COLUMN(CurrencyFieldColumn)
DECL_COLUMN(CheckBoxColumn)
DECL_COLUMN(ComboBoxColumn)
DECL_COLUMN(ListBoxColumn)
DECL_COLUMN(FormattedFieldColumn)

#endif // _FRM_COLUMNS_HXX

//.........................................................................
}   // namespace frm
//.........................................................................

<|endoftext|>


<commit_before>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE
#define DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE

#include <dune/fem/function/common/function.hh>
#include <dune/multiscale/problems/constants.hh>
#include <dune/multiscale/problems/base.hh>

namespace Dune {
namespace Multiscale {
namespace Problem {
/** \addtogroup problem_9 Problem::Nine
 * @{ **/
//! ------------ Elliptic Problem 9 -------------------

// linear elliptic model problem - periodic setting

//! For more further details about the implementation see '../base.hh'
//! For details on the classes, see 'example.hh'

// if the diffusion matrix is symmetric, we can use a CG solver, if not, default to BiCGStab.
#define SYMMETRIC_DIFFUSION_MATRIX

namespace Nine {

//! model problem information
struct ModelProblemData
  : public IModelProblemData
{
  static const bool has_exact_solution = true;
  ModelProblemData();

  //! \copydoc IModelProblemData::getMacroGridFile();
  std::string getMacroGridFile() const;

  //! are the coefficients periodic? (e.g. A=A(x/eps))
  //! this method is only relevant if you want to use a standard homogenizer
  bool problemIsPeriodic() const;

  //! does the problem allow a stochastic perturbation of the coefficients?
  bool problemAllowsStochastics() const;
};

//! ----------------- Definition of ' f ' ------------------------

class FirstSource
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType,
                                FirstSource >
{
private:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType  RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  static const int dimDomain = DomainType::dimension;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  FirstSource();

  //! evaluate f, i.e. return y=f(x) for a given x
  //! the following method defines 'f':
  void evaluate(const DomainType& x, RangeType& y) const;

  void evaluate(const DomainType& x, const TimeType& /*time*/, RangeType& y) const;
};

/** \brief default class for the second source term G.
 * Realization: set G(x) = 0: **/
MSNULLFUNCTION(SecondSource)

//! the linear diffusion operator A^{\epsilon}(x,\xi)=A^{\epsilon}(x) \xi
//! A^{\epsilon} : \Omega × R² -> R²
class Diffusion
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType, Diffusion >
{
public:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType        DomainType;
  typedef typename FunctionSpaceType::RangeType         RangeType;
  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  Diffusion();
  //! in the linear setting, use the structure
  //! A^{\epsilon}_i(x,\xi) = A^{\epsilon}_{i1}(x) \xi_1 + A^{\epsilon}_{i2}(x) \xi_2
  //! (diffusive) flux = A^{\epsilon}( x , direction )
  //! (typically direction is some 'gradient_of_a_function')
  void diffusiveFlux(const DomainType& x,
                     const JacobianRangeType& direction,
                     JacobianRangeType& flux) const;

  //! the jacobian matrix (JA^{\epsilon}) of the diffusion operator A^{\epsilon} at the position "\nabla v" in direction
  //! "nabla w", i.e.
  //! jacobian diffusiv flux = JA^{\epsilon}(\nabla v) nabla w:
  //! jacobianDiffusiveFlux = A^{\epsilon}( x , position_gradient ) direction_gradient
  void jacobianDiffusiveFlux(const DomainType& x,
                             const JacobianRangeType& /*position_gradient*/,
                             const JacobianRangeType& direction_gradient,
                             JacobianRangeType& flux) const;
};

// dummmy for a lower order term F( x , u(x) , grad u(x) ) in a PDE like
// - div ( A grad u ) + F ( x , u(x) , grad u(x) ) = f
// NOTE: the operator describing the pde must be a monotone operator
//! ------- Definition of the (possibly nonlinear) lower term F ---------
class LowerOrderTerm
//  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType,
//                                LowerOrderTerm >
{

public:

  LowerOrderTerm( /*double scaling_factor = 1.0*/ ){} // : scaling_factor_( scaling_factor ) {}

  template< class DomainType , class RangeType >
  void evaluate(const DomainType& x, RangeType& y) const
  {}

  template< class DomainType , class TimeType, class RangeType >
  void evaluate(const DomainType& x, const TimeType& /*time*/, RangeType& y) const
  {}

  template< class DomainType , class RangeType, class JacobianRangeType >
  void evaluate(const DomainType& x, const RangeType& position, const JacobianRangeType& direction_gradient, RangeType& y) const
  {}

  template< class DomainType , class RangeType, class JacobianRangeType >
  void position_derivative(const DomainType& x, const RangeType& position, const JacobianRangeType& direction_gradient, RangeType& y) const
  {}

  template< class DomainType , class RangeType, class JacobianRangeType >
  void direction_derivative(const DomainType& x, const RangeType& position, const JacobianRangeType& direction_gradient, JacobianRangeType& y) const
  {}

};

//! ----------------- Definition of ' m ' ----------------------------
MSCONSTANTFUNCTION(MassTerm,  0.0)

//! ----------------- Definition of some dummy -----------------------
MSNULLFUNCTION(DefaultDummyFunction)

//! ----------------- Definition of ' u ' ----------------------------
//! Exact solution (typically it is unknown)
class ExactSolution
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType, ExactSolution >
{
public:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType  RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  ExactSolution();

  // evaluate 'u(x)'
  void evaluate(const DomainType& x, RangeType& y) const;

  // evaluate 'grad u(x)'
  void jacobian(const DomainType& x, typename FunctionSpaceType::JacobianRangeType& grad_u) const;

  // in case 'u' HAS a time-dependency use the following method:
  // unfortunately GRAPE requires both cases of the method 'evaluate' to be
  // instantiated
  void evaluate(const DomainType& x, const TimeType&, RangeType& y) const;
};

} //! @} namespace Nine {
}
} //namespace Multiscale {
} //namespace Dune {

#endif // ifndef DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE
<commit_msg>Please don't litter the problems with empty implementations<commit_after>// dune-multiscale
// Copyright Holders: Patrick Henning, Rene Milk
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE
#define DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE

#include <dune/fem/function/common/function.hh>
#include <dune/multiscale/problems/constants.hh>
#include <dune/multiscale/problems/base.hh>

namespace Dune {
namespace Multiscale {
namespace Problem {
/** \addtogroup problem_9 Problem::Nine
 * @{ **/
//! ------------ Elliptic Problem 9 -------------------

// linear elliptic model problem - periodic setting

//! For more further details about the implementation see '../base.hh'
//! For details on the classes, see 'example.hh'

// if the diffusion matrix is symmetric, we can use a CG solver, if not, default to BiCGStab.
#define SYMMETRIC_DIFFUSION_MATRIX

namespace Nine {

//! model problem information
struct ModelProblemData
  : public IModelProblemData
{
  static const bool has_exact_solution = true;
  ModelProblemData();

  //! \copydoc IModelProblemData::getMacroGridFile();
  std::string getMacroGridFile() const;

  //! are the coefficients periodic? (e.g. A=A(x/eps))
  //! this method is only relevant if you want to use a standard homogenizer
  bool problemIsPeriodic() const;

  //! does the problem allow a stochastic perturbation of the coefficients?
  bool problemAllowsStochastics() const;
};

//! ----------------- Definition of ' f ' ------------------------

class FirstSource
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType,
                                FirstSource >
{
private:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType  RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  static const int dimDomain = DomainType::dimension;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  FirstSource();

  //! evaluate f, i.e. return y=f(x) for a given x
  //! the following method defines 'f':
  void evaluate(const DomainType& x, RangeType& y) const;

  void evaluate(const DomainType& x, const TimeType& /*time*/, RangeType& y) const;
};

/** \brief default class for the second source term G.
 * Realization: set G(x) = 0: **/
MSNULLFUNCTION(SecondSource)

//! the linear diffusion operator A^{\epsilon}(x,\xi)=A^{\epsilon}(x) \xi
//! A^{\epsilon} : \Omega × R² -> R²
class Diffusion
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType, Diffusion >
{
public:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType        DomainType;
  typedef typename FunctionSpaceType::RangeType         RangeType;
  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  Diffusion();
  //! in the linear setting, use the structure
  //! A^{\epsilon}_i(x,\xi) = A^{\epsilon}_{i1}(x) \xi_1 + A^{\epsilon}_{i2}(x) \xi_2
  //! (diffusive) flux = A^{\epsilon}( x , direction )
  //! (typically direction is some 'gradient_of_a_function')
  void diffusiveFlux(const DomainType& x,
                     const JacobianRangeType& direction,
                     JacobianRangeType& flux) const;

  //! the jacobian matrix (JA^{\epsilon}) of the diffusion operator A^{\epsilon} at the position "\nabla v" in direction
  //! "nabla w", i.e.
  //! jacobian diffusiv flux = JA^{\epsilon}(\nabla v) nabla w:
  //! jacobianDiffusiveFlux = A^{\epsilon}( x , position_gradient ) direction_gradient
  void jacobianDiffusiveFlux(const DomainType& x,
                             const JacobianRangeType& /*position_gradient*/,
                             const JacobianRangeType& direction_gradient,
                             JacobianRangeType& flux) const;
};

// dummmy for a lower order term F( x , u(x) , grad u(x) ) in a PDE like
// - div ( A grad u ) + F ( x , u(x) , grad u(x) ) = f
// NOTE: the operator describing the pde must be a monotone operator
//! ------- Definition of the (possibly nonlinear) lower term F ---------
MSCONSTANTFUNCTION(LowerOrderTerm,  0.0)

//! ----------------- Definition of ' m ' ----------------------------
MSCONSTANTFUNCTION(MassTerm,  0.0)

//! ----------------- Definition of some dummy -----------------------
MSNULLFUNCTION(DefaultDummyFunction)

//! ----------------- Definition of ' u ' ----------------------------
//! Exact solution (typically it is unknown)
class ExactSolution
  : public Dune::Fem::Function< Dune::Multiscale::CommonTraits::FunctionSpaceType, ExactSolution >
{
public:
  typedef Dune::Multiscale::CommonTraits::FunctionSpaceType FunctionSpaceType;

public:
  typedef typename FunctionSpaceType::DomainType DomainType;
  typedef typename FunctionSpaceType::RangeType  RangeType;

  typedef typename FunctionSpaceType::JacobianRangeType JacobianRangeType;

  typedef typename FunctionSpaceType::DomainFieldType DomainFieldType;
  typedef typename FunctionSpaceType::RangeFieldType  RangeFieldType;

  typedef DomainFieldType TimeType;

public:
  ExactSolution();

  // evaluate 'u(x)'
  void evaluate(const DomainType& x, RangeType& y) const;

  // evaluate 'grad u(x)'
  void jacobian(const DomainType& x, typename FunctionSpaceType::JacobianRangeType& grad_u) const;

  // in case 'u' HAS a time-dependency use the following method:
  // unfortunately GRAPE requires both cases of the method 'evaluate' to be
  // instantiated
  void evaluate(const DomainType& x, const TimeType&, RangeType& y) const;
};

} //! @} namespace Nine {
}
} //namespace Multiscale {
} //namespace Dune {

#endif // ifndef DUNE_ELLIPTIC_MODEL_PROBLEM_SPECIFICATION_HH_NINE
<|endoftext|>


<commit_before>// Copyright 2016 AUV-IITK
#include <ros.h>
#include <Arduino.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Float64.h>
#include <math.h>

#define pwmPinWest 3
#define pwmPinEast 2
#define directionPinWest1 30
#define directionPinWest2 31
#define directionPinEast1 33
#define directionPinEast2 32

#define pwmPinNorthSway 5
#define pwmPinSouthSway 4
#define directionPinNorthSway1 26
#define directionPinNorthSway2 27
#define directionPinSouthSway1 28
#define directionPinSouthSway2 29

#define pwmPinNorthUp 6
#define pwmPinSouthUp 7
#define directionPinNorthUp1 24
#define directionPinNorthUp2 25
#define directionPinSouthUp1 22
#define directionPinSouthUp2 23

#define analogPinPressureSensor A0

const float c092 = 506.22;
const float s092 = -2.65;
const float c093 = 448.62;
const float s093 = -2.92;
const float c099 = 397.65;  // reference as their graph is at lowest
const float s099 = -2.71;   // reference as their graph is at lowest
const float c113 = 539.85;
const float s113 = -3.38;
const float c117 = 441.32;
const float s117 = -3.03;
const float c122 = 547.39;
const float s122 = -2.93;

bool isMovingForward = true;
float v;
std_msgs::Float64 voltage;
ros::NodeHandle nh;

int btd092(int pwm)
{
  pwm = (c099 + s099 * pwm - c092) / (s092);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd093(int pwm)
{
  pwm = (c099 + s099 * pwm - c093) / (s093);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd099(int pwm)
{
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd113(int pwm)
{
  pwm = (c099 + s099 * pwm - c113) / (s113);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd117(int pwm)
{
  pwm = (c099 + s099 * pwm - c117) / (s117);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd122(int pwm)
{
  pwm = (c099 + s099 * pwm - c122) / (s122);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

void thrusterNorthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd117(pwm);
  analogWrite(pwmPinNorthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinNorthUp1, HIGH);
    digitalWrite(directionPinNorthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthUp1, LOW);
    digitalWrite(directionPinNorthUp2, HIGH);
  }
}

void thrusterSouthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd093(pwm);
  analogWrite(pwmPinSouthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinSouthUp1, HIGH);
    digitalWrite(directionPinSouthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthUp1, LOW);
    digitalWrite(directionPinSouthUp2, HIGH);
  }
}

void thrusterNorthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd113(pwm);
  analogWrite(pwmPinNorthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinNorthSway1, HIGH);
    digitalWrite(directionPinNorthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthSway1, LOW);
    digitalWrite(directionPinNorthSway2, HIGH);
  }
}

void thrusterSouthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd122(pwm);
  analogWrite(pwmPinSouthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinSouthSway1, HIGH);
    digitalWrite(directionPinSouthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthSway1, LOW);
    digitalWrite(directionPinSouthSway2, HIGH);
  }
}

void thrusterEast(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd092(pwm);
  analogWrite(pwmPinEast, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinEast1, HIGH);
    digitalWrite(directionPinEast2, LOW);
  }
  else
  {
    digitalWrite(directionPinEast1, LOW);
    digitalWrite(directionPinEast2, HIGH);
  }
}

void thrusterWest(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd099(pwm);
  analogWrite(pwmPinWest, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinWest1, HIGH);
    digitalWrite(directionPinWest2, LOW);
  }
  else
  {
    digitalWrite(directionPinWest1, LOW);
    digitalWrite(directionPinWest2, HIGH);
  }
}

void PWMCbForward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterEast(msg.data, true);
    thrusterWest(msg.data, true);
  }
  else
  {
    thrusterEast(msg.data, false);
    thrusterWest(msg.data, false);
  }
  isMovingForward = true;
}

void PWMCbSideward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthSway(msg.data, true);
    thrusterSouthSway(msg.data, true);
  }
  else
  {
    thrusterNorthSway(msg.data, false);
    thrusterSouthSway(msg.data, false);
  }
  isMovingForward = false;
}

void PWMCbUpward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthUp(msg.data, true);
    thrusterSouthUp(msg.data, true);
  }
  else
  {
    thrusterNorthUp(msg.data, false);
    thrusterSouthUp(msg.data, false);
  }
}

void PWMCbTurn(const std_msgs::Int32& msg)
{
  if (!isMovingForward)
  {
    if (msg.data > 0)
    {
      thrusterEast(msg.data, true);
      thrusterWest(msg.data, false);
    }
    else
    {
      thrusterEast(msg.data, false);
      thrusterWest(msg.data, true);
    }
  }
  else
  {
    if (msg.data > 0)
    {
      thrusterNorthSway(msg.data, false);
      thrusterSouthSway(msg.data, true);
    }
    else
    {
      thrusterNorthSway(msg.data, true);
      thrusterSouthSway(msg.data, false);
    }
  }
}

ros::Subscriber<std_msgs::Int32> subPwmForward("/pwm/forward", &PWMCbForward);
ros::Subscriber<std_msgs::Int32> subPwmSideward("/pwm/sideward", &PWMCbSideward);
ros::Subscriber<std_msgs::Int32> subPwmUpward("/pwm/upward", &PWMCbUpward);
ros::Subscriber<std_msgs::Int32> subPwmTurn("/pwm/turn", &PWMCbTurn);
ros::Publisher ps_voltage("zDistance", &voltage);

void setup()
{
  nh.initNode();

  pinMode(pwmPinEast, OUTPUT);
  pinMode(directionPinEast1, OUTPUT);
  pinMode(directionPinEast2, OUTPUT);
  pinMode(pwmPinWest, OUTPUT);
  pinMode(directionPinWest1, OUTPUT);
  pinMode(directionPinWest2, OUTPUT);

  pinMode(directionPinSouthSway1, OUTPUT);
  pinMode(directionPinSouthSway2, OUTPUT);
  pinMode(pwmPinNorthSway, OUTPUT);
  pinMode(directionPinNorthSway2, OUTPUT);
  pinMode(pwmPinSouthSway, OUTPUT);
  pinMode(directionPinNorthSway1, OUTPUT);

  pinMode(directionPinSouthUp1, OUTPUT);
  pinMode(directionPinSouthUp2, OUTPUT);
  pinMode(pwmPinNorthUp, OUTPUT);
  pinMode(directionPinNorthUp2, OUTPUT);
  pinMode(pwmPinSouthUp, OUTPUT);
  pinMode(directionPinNorthUp1, OUTPUT);

  nh.subscribe(subPwmForward);
  nh.subscribe(subPwmSideward);
  nh.subscribe(subPwmUpward);
  nh.subscribe(subPwmTurn);
  nh.advertise(ps_voltage);
  Serial.begin(57600);
  std_msgs::Int32 msg;
  msg.data = 0;
  PWMCbForward(msg);
  PWMCbSideward(msg);
  PWMCbUpward(msg);
  PWMCbTurn(msg);
}

void loop()
{
  v = analogRead(analogPinPressureSensor);
  voltage.data = -v;  // negative because convention is to take upward direction as positive
  ps_voltage.publish(&voltage);
  nh.spinOnce();
  delay(100);
}
<commit_msg>pressure sensor filteration added in main arduino node<commit_after>// Copyright 2016 AUV-IITK
#include <ros.h>
#include <Arduino.h>
#include <std_msgs/Int32.h>
#include <std_msgs/Float64.h>
#include <math.h>

#define pwmPinWest 3
#define pwmPinEast 2
#define directionPinWest1 30
#define directionPinWest2 31
#define directionPinEast1 33
#define directionPinEast2 32

#define pwmPinNorthSway 5
#define pwmPinSouthSway 4
#define directionPinNorthSway1 26
#define directionPinNorthSway2 27
#define directionPinSouthSway1 28
#define directionPinSouthSway2 29

#define pwmPinNorthUp 6
#define pwmPinSouthUp 7
#define directionPinNorthUp1 24
#define directionPinNorthUp2 25
#define directionPinSouthUp1 22
#define directionPinSouthUp2 23

#define analogPinPressureSensor A0

const float c092 = 506.22;
const float s092 = -2.65;
const float c093 = 448.62;
const float s093 = -2.92;
const float c099 = 397.65;  // reference as their graph is at lowest
const float s099 = -2.71;   // reference as their graph is at lowest
const float c113 = 539.85;
const float s113 = -3.38;
const float c117 = 441.32;
const float s117 = -3.03;
const float c122 = 547.39;
const float s122 = -2.93;

int count, sum;
bool isMovingForward = true;
float v;
std_msgs::Float64 voltage;
ros::NodeHandle nh;

int btd092(int pwm)
{
  pwm = (c099 + s099 * pwm - c092) / (s092);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd093(int pwm)
{
  pwm = (c099 + s099 * pwm - c093) / (s093);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd099(int pwm)
{
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd113(int pwm)
{
  pwm = (c099 + s099 * pwm - c113) / (s113);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd117(int pwm)
{
  pwm = (c099 + s099 * pwm - c117) / (s117);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

int btd122(int pwm)
{
  pwm = (c099 + s099 * pwm - c122) / (s122);
  if (pwm < 147)
    return 0;
  if (pwm > 255)
    return 255;
  return pwm;
}

void thrusterNorthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd117(pwm);
  analogWrite(pwmPinNorthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinNorthUp1, HIGH);
    digitalWrite(directionPinNorthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthUp1, LOW);
    digitalWrite(directionPinNorthUp2, HIGH);
  }
}

void thrusterSouthUp(int pwm, int isUpward)
{
  pwm = abs(pwm);
  pwm = btd093(pwm);
  analogWrite(pwmPinSouthUp, 255 - pwm);
  if (isUpward)
  {
    digitalWrite(directionPinSouthUp1, HIGH);
    digitalWrite(directionPinSouthUp2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthUp1, LOW);
    digitalWrite(directionPinSouthUp2, HIGH);
  }
}

void thrusterNorthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd113(pwm);
  analogWrite(pwmPinNorthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinNorthSway1, HIGH);
    digitalWrite(directionPinNorthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinNorthSway1, LOW);
    digitalWrite(directionPinNorthSway2, HIGH);
  }
}

void thrusterSouthSway(int pwm, int isRight)
{
  pwm = abs(pwm);
  pwm = btd122(pwm);
  analogWrite(pwmPinSouthSway, 255 - pwm);
  if (isRight)
  {
    digitalWrite(directionPinSouthSway1, HIGH);
    digitalWrite(directionPinSouthSway2, LOW);
  }
  else
  {
    digitalWrite(directionPinSouthSway1, LOW);
    digitalWrite(directionPinSouthSway2, HIGH);
  }
}

void thrusterEast(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd092(pwm);
  analogWrite(pwmPinEast, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinEast1, HIGH);
    digitalWrite(directionPinEast2, LOW);
  }
  else
  {
    digitalWrite(directionPinEast1, LOW);
    digitalWrite(directionPinEast2, HIGH);
  }
}

void thrusterWest(int pwm, int isForward)
{
  pwm = abs(pwm);
  pwm = btd099(pwm);
  analogWrite(pwmPinWest, 255 - pwm);
  if (isForward)
  {
    digitalWrite(directionPinWest1, HIGH);
    digitalWrite(directionPinWest2, LOW);
  }
  else
  {
    digitalWrite(directionPinWest1, LOW);
    digitalWrite(directionPinWest2, HIGH);
  }
}

void PWMCbForward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterEast(msg.data, true);
    thrusterWest(msg.data, true);
  }
  else
  {
    thrusterEast(msg.data, false);
    thrusterWest(msg.data, false);
  }
  isMovingForward = true;
}

void PWMCbSideward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthSway(msg.data, true);
    thrusterSouthSway(msg.data, true);
  }
  else
  {
    thrusterNorthSway(msg.data, false);
    thrusterSouthSway(msg.data, false);
  }
  isMovingForward = false;
}

void PWMCbUpward(const std_msgs::Int32& msg)
{
  if (msg.data > 0)
  {
    thrusterNorthUp(msg.data, true);
    thrusterSouthUp(msg.data, true);
  }
  else
  {
    thrusterNorthUp(msg.data, false);
    thrusterSouthUp(msg.data, false);
  }
}

void PWMCbTurn(const std_msgs::Int32& msg)
{
  if (!isMovingForward)
  {
    if (msg.data > 0)
    {
      thrusterEast(msg.data, true);
      thrusterWest(msg.data, false);
    }
    else
    {
      thrusterEast(msg.data, false);
      thrusterWest(msg.data, true);
    }
  }
  else
  {
    if (msg.data > 0)
    {
      thrusterNorthSway(msg.data, false);
      thrusterSouthSway(msg.data, true);
    }
    else
    {
      thrusterNorthSway(msg.data, true);
      thrusterSouthSway(msg.data, false);
    }
  }
}

ros::Subscriber<std_msgs::Int32> subPwmForward("/pwm/forward", &PWMCbForward);
ros::Subscriber<std_msgs::Int32> subPwmSideward("/pwm/sideward", &PWMCbSideward);
ros::Subscriber<std_msgs::Int32> subPwmUpward("/pwm/upward", &PWMCbUpward);
ros::Subscriber<std_msgs::Int32> subPwmTurn("/pwm/turn", &PWMCbTurn);
ros::Publisher ps_voltage("zDistance", &voltage);

void setup()
{
  nh.initNode();

  pinMode(pwmPinEast, OUTPUT);
  pinMode(directionPinEast1, OUTPUT);
  pinMode(directionPinEast2, OUTPUT);
  pinMode(pwmPinWest, OUTPUT);
  pinMode(directionPinWest1, OUTPUT);
  pinMode(directionPinWest2, OUTPUT);

  pinMode(directionPinSouthSway1, OUTPUT);
  pinMode(directionPinSouthSway2, OUTPUT);
  pinMode(pwmPinNorthSway, OUTPUT);
  pinMode(directionPinNorthSway2, OUTPUT);
  pinMode(pwmPinSouthSway, OUTPUT);
  pinMode(directionPinNorthSway1, OUTPUT);

  pinMode(directionPinSouthUp1, OUTPUT);
  pinMode(directionPinSouthUp2, OUTPUT);
  pinMode(pwmPinNorthUp, OUTPUT);
  pinMode(directionPinNorthUp2, OUTPUT);
  pinMode(pwmPinSouthUp, OUTPUT);
  pinMode(directionPinNorthUp1, OUTPUT);

  nh.subscribe(subPwmForward);
  nh.subscribe(subPwmSideward);
  nh.subscribe(subPwmUpward);
  nh.subscribe(subPwmTurn);
  nh.advertise(ps_voltage);
  Serial.begin(57600);
  std_msgs::Int32 msg;
  msg.data = 0;
  PWMCbForward(msg);
  PWMCbSideward(msg);
  PWMCbUpward(msg);
  PWMCbTurn(msg);
  count = 0;
  sum = 0;
}

void loop()
{
  if (count == 100)
  {
    sum /= count;
    voltage.data = -sum;  // negative because convention is to take upward direction as positive
    ps_voltage.publish(&voltage);
    sum = 0;
    count = 0;
  }
  else
  {
    v = analogRead(analogPinPressureSensor);
    sum += v;
    count++;
    delay(1);
  }
  nh.spinOnce();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: textconversion_zh.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 04:49:18 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#include <assert.h>
#include <textconversion.hxx>
#include <com/sun/star/i18n/TextConversionType.hpp>
#include <com/sun/star/i18n/TextConversionOption.hpp>
#include <com/sun/star/linguistic2/ConversionDirection.hpp>
#include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
#include <i18nutil/x_rtl_ustring.h>

using namespace com::sun::star::lang;
using namespace com::sun::star::i18n;
using namespace com::sun::star::linguistic2;
using namespace com::sun::star::uno;
using namespace rtl;

namespace com { namespace sun { namespace star { namespace i18n {

TextConversion_zh::TextConversion_zh( const Reference < XMultiServiceFactory >& xMSF )
{
    Reference < XInterface > xI;
    xI = xMSF->createInstance(
        OUString::createFromAscii( "com.sun.star.linguistic2.ConversionDictionaryList" ));
    if ( xI.is() )
        xI->queryInterface( getCppuType((const Reference< XConversionDictionaryList>*)0) ) >>= xCDL;

    implementationName = "com.sun.star.i18n.TextConversion_zh";
}

sal_Unicode SAL_CALL getOneCharConversion(sal_Unicode ch, const sal_Unicode* Data, const sal_uInt16* Index)
{
    if (Data && Index) {
        sal_Unicode address = Index[ch>>8];
        if (address != 0xFFFF)
            address = Data[address + (ch & 0xFF)];
        return (address != 0xFFFF) ? address : ch;
    } else {
        return ch;
    }
}

OUString SAL_CALL
TextConversion_zh::getCharConversion(const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, sal_Bool toSChinese, sal_Int32 nConversionOptions)
{
    const sal_Unicode *Data;
    const sal_uInt16 *Index;

    if (toSChinese) {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_T2S"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_T2S"))();
    } else if (nConversionOptions & TextConversionOption::USE_CHARACTER_VARIANTS) {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_S2V"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_S2V"))();
    } else {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_S2T"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_S2T"))();
    }

    rtl_uString * newStr = x_rtl_uString_new_WithLength( nLength ); // defined in x_rtl_ustring.h
    for (sal_Int32 i = 0; i < nLength; i++)
        newStr->buffer[i] =
            getOneCharConversion(aText[nStartPos+i], Data, Index);
    return OUString( newStr->buffer, nLength);
}

OUString SAL_CALL
TextConversion_zh::getWordConversion(const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, sal_Bool toSChinese, sal_Int32 nConversionOptions, Sequence<sal_Int32>& offset)
{
    sal_Int32 dictLen = 0;
    sal_Int32 maxLen = 0;
    const sal_uInt16 *index;
    const sal_uInt16 *entry;
    const sal_Unicode *charData;
    const sal_uInt16 *charIndex;
    sal_Bool one2one=sal_True;

    const sal_Unicode *wordData = ((const sal_Unicode* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordData"))(dictLen);
    if (toSChinese) {
        index = ((const sal_uInt16* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordIndex_T2S"))(maxLen);
        entry = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_WordEntry_T2S"))();
        charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_T2S"))();
        charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_T2S"))();
    } else {
        index = ((const sal_uInt16* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordIndex_S2T"))(maxLen);
        entry = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_WordEntry_S2T"))();
        if (nConversionOptions & TextConversionOption::USE_CHARACTER_VARIANTS) {
            charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_S2V"))();
            charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_S2V"))();
        } else {
            charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_S2T"))();
            charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_S2T"))();
        }
    }

    if ((!wordData || !index || !entry) && !xCDL.is()) // no word mapping defined, do char2char conversion.
        return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);

    rtl_uString * newStr = x_rtl_uString_new_WithLength( nLength * 2 ); // defined in x_rtl_ustring.h
    sal_Int32 currPos = 0, count = 0;
    while (currPos < nLength) {
        sal_Int32 len = nLength - currPos;
        sal_Bool found = sal_False;
        if (len > maxLen)
            len = maxLen;
        for (; len > 0 && ! found; len--) {
            OUString word = aText.copy(nStartPos + currPos, len);
            sal_Int32 current = 0;
            // user dictionary
            if (xCDL.is()) {
                Sequence < OUString > conversions;
                try {
                    conversions = xCDL->queryConversions(word, 0, len,
                            aLocale, ConversionDictionaryType::SCHINESE_TCHINESE,
                            /*toSChinese ?*/ ConversionDirection_FROM_LEFT /*: ConversionDirection_FROM_RIGHT*/,
                            nConversionOptions);
                }
                catch ( NoSupportException & ) {
                    // clear reference (when there is no user dictionary) in order
                    // to not always have to catch this exception again
                    // in further calls. (save time)
                    xCDL = 0;
                }
                catch (...) {
                    // catch all other exceptions to allow
                    // querying the system dictionary in the next line
                }
                if (conversions.getLength() > 0) {
                    if (offset.getLength() > 0) {
                        if (word.getLength() != conversions[0].getLength())
                            one2one=sal_False;
                        while (current < conversions[0].getLength()) {
                            offset[count] = nStartPos + currPos + (current *
                                    word.getLength() / conversions[0].getLength());
                            newStr->buffer[count++] = conversions[0][current++];
                        }
                        offset[count-1] = nStartPos + currPos + word.getLength() - 1;
                    } else {
                        while (current < conversions[0].getLength())
                            newStr->buffer[count++] = conversions[0][current++];
                    }
                    currPos += word.getLength();
                    found = sal_True;
                }
            }

            if (!found && index[len+1] - index[len] > 0) {
                sal_Int32 bottom = (sal_Int32) index[len];
                sal_Int32 top = (sal_Int32) index[len+1] - 1;

                while (bottom <= top && !found) {
                    current = (top + bottom) / 2;
                    const sal_Int32 result = word.compareTo(wordData + entry[current]);
                    if (result < 0)
                        top = current - 1;
                    else if (result > 0)
                        bottom = current + 1;
                    else {
                        if (toSChinese)   // Traditionary/Simplified conversion,
                            for (current = entry[current]-1; current > 0 && wordData[current-1]; current--);
                        else  // Simplified/Traditionary conversion, forwards search for next word
                            current = entry[current] + word.getLength() + 1;
                        sal_Int32 start=current;
                        if (offset.getLength() > 0) {
                            if (word.getLength() != OUString(&wordData[current]).getLength())
                                one2one=sal_False;
                            sal_Int32 convertedLength=OUString(&wordData[current]).getLength();
                            while (wordData[current]) {
                                offset[count]=nStartPos + currPos + ((current-start) *
                                    word.getLength() / convertedLength);
                                newStr->buffer[count++] = wordData[current++];
                            }
                            offset[count-1]=nStartPos + currPos + word.getLength() - 1;
                        } else {
                            while (wordData[current])
                                newStr->buffer[count++] = wordData[current++];
                        }
                        currPos += word.getLength();
                        found = sal_True;
                    }
                }
            }
        }
        if (!found) {
            if (offset.getLength() > 0)
                offset[count]=nStartPos+currPos;
            newStr->buffer[count++] =
                getOneCharConversion(aText[nStartPos+currPos], charData, charIndex);
            currPos++;
        }
    }
    if (offset.getLength() > 0)
        offset.realloc(one2one ? 0 : count);
    return OUString( newStr->buffer, count);
}

TextConversionResult SAL_CALL
TextConversion_zh::getConversions( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    TextConversionResult result;

    result.Candidates.realloc(1);
    result.Candidates[0] = getConversion( aText, nStartPos, nLength, rLocale, nConversionType, nConversionOptions);
    result.Boundary.startPos = nStartPos;
    result.Boundary.endPos = nStartPos + nLength;

    return result;
}

OUString SAL_CALL
TextConversion_zh::getConversion( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    if (rLocale.Language.equalsAscii("zh") &&
            ( nConversionType == TextConversionType::TO_SCHINESE ||
            nConversionType == TextConversionType::TO_TCHINESE) ) {

        aLocale=rLocale;
        sal_Bool toSChinese = nConversionType == TextConversionType::TO_SCHINESE;

        if (nConversionOptions & TextConversionOption::CHARACTER_BY_CHARACTER)
            // char to char dictionary
            return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);
        else {
            Sequence <sal_Int32> offset;
            // word to word dictionary
            return  getWordConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions, offset);
        }
    } else
        throw NoSupportException(); // Conversion type is not supported in this service.
}

OUString SAL_CALL
TextConversion_zh::getConversionWithOffset( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions, Sequence<sal_Int32>& offset)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    if (rLocale.Language.equalsAscii("zh") &&
            ( nConversionType == TextConversionType::TO_SCHINESE ||
            nConversionType == TextConversionType::TO_TCHINESE) ) {

        aLocale=rLocale;
        sal_Bool toSChinese = nConversionType == TextConversionType::TO_SCHINESE;

        if (nConversionOptions & TextConversionOption::CHARACTER_BY_CHARACTER) {
            offset.realloc(0);
            // char to char dictionary
            return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);
        } else {
            if (offset.getLength() < 2*nLength)
                offset.realloc(2*nLength);
            // word to word dictionary
            return  getWordConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions, offset);
        }
    } else
        throw NoSupportException(); // Conversion type is not supported in this service.
}

sal_Bool SAL_CALL
TextConversion_zh::interactiveConversion( const Locale& /*rLocale*/, sal_Int16 /*nTextConversionType*/, sal_Int32 /*nTextConversionOptions*/ )
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    return sal_False;
}

} } } }
<commit_msg>INTEGRATION: CWS pchfix02 (1.8.16); FILE MERGED 2006/09/01 17:30:49 kaib 1.8.16.1: #i68856# Added header markers and pch files<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: textconversion_zh.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 09:24:29 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library 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
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_i18npool.hxx"

#include <assert.h>
#include <textconversion.hxx>
#include <com/sun/star/i18n/TextConversionType.hpp>
#include <com/sun/star/i18n/TextConversionOption.hpp>
#include <com/sun/star/linguistic2/ConversionDirection.hpp>
#include <com/sun/star/linguistic2/ConversionDictionaryType.hpp>
#include <i18nutil/x_rtl_ustring.h>

using namespace com::sun::star::lang;
using namespace com::sun::star::i18n;
using namespace com::sun::star::linguistic2;
using namespace com::sun::star::uno;
using namespace rtl;

namespace com { namespace sun { namespace star { namespace i18n {

TextConversion_zh::TextConversion_zh( const Reference < XMultiServiceFactory >& xMSF )
{
    Reference < XInterface > xI;
    xI = xMSF->createInstance(
        OUString::createFromAscii( "com.sun.star.linguistic2.ConversionDictionaryList" ));
    if ( xI.is() )
        xI->queryInterface( getCppuType((const Reference< XConversionDictionaryList>*)0) ) >>= xCDL;

    implementationName = "com.sun.star.i18n.TextConversion_zh";
}

sal_Unicode SAL_CALL getOneCharConversion(sal_Unicode ch, const sal_Unicode* Data, const sal_uInt16* Index)
{
    if (Data && Index) {
        sal_Unicode address = Index[ch>>8];
        if (address != 0xFFFF)
            address = Data[address + (ch & 0xFF)];
        return (address != 0xFFFF) ? address : ch;
    } else {
        return ch;
    }
}

OUString SAL_CALL
TextConversion_zh::getCharConversion(const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, sal_Bool toSChinese, sal_Int32 nConversionOptions)
{
    const sal_Unicode *Data;
    const sal_uInt16 *Index;

    if (toSChinese) {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_T2S"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_T2S"))();
    } else if (nConversionOptions & TextConversionOption::USE_CHARACTER_VARIANTS) {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_S2V"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_S2V"))();
    } else {
        Data = ((const sal_Unicode* (*)())getFunctionBySymbol("getSTC_CharData_S2T"))();
        Index = ((const sal_uInt16* (*)())getFunctionBySymbol("getSTC_CharIndex_S2T"))();
    }

    rtl_uString * newStr = x_rtl_uString_new_WithLength( nLength ); // defined in x_rtl_ustring.h
    for (sal_Int32 i = 0; i < nLength; i++)
        newStr->buffer[i] =
            getOneCharConversion(aText[nStartPos+i], Data, Index);
    return OUString( newStr->buffer, nLength);
}

OUString SAL_CALL
TextConversion_zh::getWordConversion(const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength, sal_Bool toSChinese, sal_Int32 nConversionOptions, Sequence<sal_Int32>& offset)
{
    sal_Int32 dictLen = 0;
    sal_Int32 maxLen = 0;
    const sal_uInt16 *index;
    const sal_uInt16 *entry;
    const sal_Unicode *charData;
    const sal_uInt16 *charIndex;
    sal_Bool one2one=sal_True;

    const sal_Unicode *wordData = ((const sal_Unicode* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordData"))(dictLen);
    if (toSChinese) {
        index = ((const sal_uInt16* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordIndex_T2S"))(maxLen);
        entry = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_WordEntry_T2S"))();
        charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_T2S"))();
        charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_T2S"))();
    } else {
        index = ((const sal_uInt16* (*)(sal_Int32&)) getFunctionBySymbol("getSTC_WordIndex_S2T"))(maxLen);
        entry = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_WordEntry_S2T"))();
        if (nConversionOptions & TextConversionOption::USE_CHARACTER_VARIANTS) {
            charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_S2V"))();
            charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_S2V"))();
        } else {
            charData = ((const sal_Unicode* (*)()) getFunctionBySymbol("getSTC_CharData_S2T"))();
            charIndex = ((const sal_uInt16* (*)()) getFunctionBySymbol("getSTC_CharIndex_S2T"))();
        }
    }

    if ((!wordData || !index || !entry) && !xCDL.is()) // no word mapping defined, do char2char conversion.
        return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);

    rtl_uString * newStr = x_rtl_uString_new_WithLength( nLength * 2 ); // defined in x_rtl_ustring.h
    sal_Int32 currPos = 0, count = 0;
    while (currPos < nLength) {
        sal_Int32 len = nLength - currPos;
        sal_Bool found = sal_False;
        if (len > maxLen)
            len = maxLen;
        for (; len > 0 && ! found; len--) {
            OUString word = aText.copy(nStartPos + currPos, len);
            sal_Int32 current = 0;
            // user dictionary
            if (xCDL.is()) {
                Sequence < OUString > conversions;
                try {
                    conversions = xCDL->queryConversions(word, 0, len,
                            aLocale, ConversionDictionaryType::SCHINESE_TCHINESE,
                            /*toSChinese ?*/ ConversionDirection_FROM_LEFT /*: ConversionDirection_FROM_RIGHT*/,
                            nConversionOptions);
                }
                catch ( NoSupportException & ) {
                    // clear reference (when there is no user dictionary) in order
                    // to not always have to catch this exception again
                    // in further calls. (save time)
                    xCDL = 0;
                }
                catch (...) {
                    // catch all other exceptions to allow
                    // querying the system dictionary in the next line
                }
                if (conversions.getLength() > 0) {
                    if (offset.getLength() > 0) {
                        if (word.getLength() != conversions[0].getLength())
                            one2one=sal_False;
                        while (current < conversions[0].getLength()) {
                            offset[count] = nStartPos + currPos + (current *
                                    word.getLength() / conversions[0].getLength());
                            newStr->buffer[count++] = conversions[0][current++];
                        }
                        offset[count-1] = nStartPos + currPos + word.getLength() - 1;
                    } else {
                        while (current < conversions[0].getLength())
                            newStr->buffer[count++] = conversions[0][current++];
                    }
                    currPos += word.getLength();
                    found = sal_True;
                }
            }

            if (!found && index[len+1] - index[len] > 0) {
                sal_Int32 bottom = (sal_Int32) index[len];
                sal_Int32 top = (sal_Int32) index[len+1] - 1;

                while (bottom <= top && !found) {
                    current = (top + bottom) / 2;
                    const sal_Int32 result = word.compareTo(wordData + entry[current]);
                    if (result < 0)
                        top = current - 1;
                    else if (result > 0)
                        bottom = current + 1;
                    else {
                        if (toSChinese)   // Traditionary/Simplified conversion,
                            for (current = entry[current]-1; current > 0 && wordData[current-1]; current--);
                        else  // Simplified/Traditionary conversion, forwards search for next word
                            current = entry[current] + word.getLength() + 1;
                        sal_Int32 start=current;
                        if (offset.getLength() > 0) {
                            if (word.getLength() != OUString(&wordData[current]).getLength())
                                one2one=sal_False;
                            sal_Int32 convertedLength=OUString(&wordData[current]).getLength();
                            while (wordData[current]) {
                                offset[count]=nStartPos + currPos + ((current-start) *
                                    word.getLength() / convertedLength);
                                newStr->buffer[count++] = wordData[current++];
                            }
                            offset[count-1]=nStartPos + currPos + word.getLength() - 1;
                        } else {
                            while (wordData[current])
                                newStr->buffer[count++] = wordData[current++];
                        }
                        currPos += word.getLength();
                        found = sal_True;
                    }
                }
            }
        }
        if (!found) {
            if (offset.getLength() > 0)
                offset[count]=nStartPos+currPos;
            newStr->buffer[count++] =
                getOneCharConversion(aText[nStartPos+currPos], charData, charIndex);
            currPos++;
        }
    }
    if (offset.getLength() > 0)
        offset.realloc(one2one ? 0 : count);
    return OUString( newStr->buffer, count);
}

TextConversionResult SAL_CALL
TextConversion_zh::getConversions( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    TextConversionResult result;

    result.Candidates.realloc(1);
    result.Candidates[0] = getConversion( aText, nStartPos, nLength, rLocale, nConversionType, nConversionOptions);
    result.Boundary.startPos = nStartPos;
    result.Boundary.endPos = nStartPos + nLength;

    return result;
}

OUString SAL_CALL
TextConversion_zh::getConversion( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    if (rLocale.Language.equalsAscii("zh") &&
            ( nConversionType == TextConversionType::TO_SCHINESE ||
            nConversionType == TextConversionType::TO_TCHINESE) ) {

        aLocale=rLocale;
        sal_Bool toSChinese = nConversionType == TextConversionType::TO_SCHINESE;

        if (nConversionOptions & TextConversionOption::CHARACTER_BY_CHARACTER)
            // char to char dictionary
            return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);
        else {
            Sequence <sal_Int32> offset;
            // word to word dictionary
            return  getWordConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions, offset);
        }
    } else
        throw NoSupportException(); // Conversion type is not supported in this service.
}

OUString SAL_CALL
TextConversion_zh::getConversionWithOffset( const OUString& aText, sal_Int32 nStartPos, sal_Int32 nLength,
    const Locale& rLocale, sal_Int16 nConversionType, sal_Int32 nConversionOptions, Sequence<sal_Int32>& offset)
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    if (rLocale.Language.equalsAscii("zh") &&
            ( nConversionType == TextConversionType::TO_SCHINESE ||
            nConversionType == TextConversionType::TO_TCHINESE) ) {

        aLocale=rLocale;
        sal_Bool toSChinese = nConversionType == TextConversionType::TO_SCHINESE;

        if (nConversionOptions & TextConversionOption::CHARACTER_BY_CHARACTER) {
            offset.realloc(0);
            // char to char dictionary
            return getCharConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions);
        } else {
            if (offset.getLength() < 2*nLength)
                offset.realloc(2*nLength);
            // word to word dictionary
            return  getWordConversion(aText, nStartPos, nLength, toSChinese, nConversionOptions, offset);
        }
    } else
        throw NoSupportException(); // Conversion type is not supported in this service.
}

sal_Bool SAL_CALL
TextConversion_zh::interactiveConversion( const Locale& /*rLocale*/, sal_Int16 /*nTextConversionType*/, sal_Int32 /*nTextConversionOptions*/ )
    throw(  RuntimeException, IllegalArgumentException, NoSupportException )
{
    return sal_False;
}

} } } }
<|endoftext|>


<commit_before>//
//  Flywheel.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/02/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef Flywheel_hpp
#define Flywheel_hpp

#include <cstdlib>
#include <cstdint>

namespace Outputs {
namespace CRT {

/*!
	Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase,
	announcing the start and end of retrace and providing the abiliy to read the current
	scanning position.

	The @c Flywheel will attempt to converge with timing implied by synchronisation pulses.
*/
struct Flywheel {
	/*!
		Constructs an instance of @c Flywheel.

		@param standard_period The expected amount of time between one synchronisation and the next.
		@param retrace_time The amount of time it takes to complete a retrace.
		@param sync_error_window The permitted deviation of sync timings from the norm.
	*/
	Flywheel(int standard_period, int retrace_time, int sync_error_window) :
		standard_period_(standard_period),
		retrace_time_(retrace_time),
		sync_error_window_(sync_error_window),
		counter_before_retrace_(standard_period - retrace_time),
		expected_next_sync_(standard_period) {}

	enum SyncEvent {
		/// Indicates that no synchronisation events will occur in the queried window.
		None,
		/// Indicates that the next synchronisation event will be a transition into retrce.
		StartRetrace,
		/// Indicates that the next synchronisation event will be a transition out of retrace.
		EndRetrace
	};
	/*!
		Asks the flywheel for the first synchronisation event that will occur in a given time period,
		indicating whether a synchronisation request occurred at the start of the query window.

		@param sync_is_requested @c true indicates that the flywheel should act as though having
		received a synchronisation request now; @c false indicates no such event was detected.

		@param cycles_to_run_for The number of cycles to look ahead.

		@param cycles_advanced After this method has completed, contains the amount of time until
		the returned synchronisation event.

		@returns The next synchronisation event.
	*/
	inline SyncEvent get_next_event_in_period(bool sync_is_requested, int cycles_to_run_for, int *cycles_advanced) {
		// do we recognise this hsync, thereby adjusting future time expectations?
		if(sync_is_requested) {
			if(counter_ < sync_error_window_ || counter_ > expected_next_sync_ - sync_error_window_) {
				const int time_now = (counter_ < sync_error_window_) ? expected_next_sync_ + counter_ : counter_;
				expected_next_sync_ = (3*expected_next_sync_ + time_now) >> 2;
			} else {
				++number_of_surprises_;

				if(counter_ < retrace_time_ + (expected_next_sync_ >> 1)) {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ + sync_error_window_) >> 2;
				} else {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ - sync_error_window_) >> 2;
				}
			}
		}

		SyncEvent proposed_event = SyncEvent::None;
		int proposed_sync_time = cycles_to_run_for;

		// will we end an ongoing retrace?
		if(counter_ < retrace_time_ && counter_ + proposed_sync_time >= retrace_time_) {
			proposed_sync_time = retrace_time_ - counter_;
			proposed_event = SyncEvent::EndRetrace;
		}

		// will we start a retrace?
		if(counter_ + proposed_sync_time >= expected_next_sync_) {
			proposed_sync_time = expected_next_sync_ - counter_;
			proposed_event = SyncEvent::StartRetrace;
		}

		*cycles_advanced = proposed_sync_time;
		return proposed_event;
	}

	/*!
		Advances a nominated amount of time, applying a previously returned synchronisation event
		at the end of that period.

		@param cycles_advanced The amount of time to run for.

		@param event The synchronisation event to apply after that period.
	*/
	inline void apply_event(int cycles_advanced, SyncEvent event) {
		counter_ += cycles_advanced;

		switch(event) {
			default: return;
			case StartRetrace:
				counter_before_retrace_ = counter_ - retrace_time_;
				counter_ = 0;
			return;
		}
	}

	/*!
		Returns the current output position; while in retrace this will go down towards 0, while in scan
		it will go upward.

		@returns The current output position.
	*/
	inline int get_current_output_position() {
		if(counter_ < retrace_time_) {
			const int retrace_distance = int((int64_t(counter_) * int64_t(standard_period_)) / int64_t(retrace_time_));
			if(retrace_distance > counter_before_retrace_) return 0;
			return counter_before_retrace_ - retrace_distance;
		}

		return counter_ - retrace_time_;
	}

	/*!
		@returns the amount of time since retrace last began. Time then counts monotonically up from zero.
	*/
	inline int get_current_time() {
		return counter_;
	}

	/*!
		@returns whether the output is currently retracing.
	*/
	inline bool is_in_retrace() {
		return counter_ < retrace_time_;
	}

	/*!
		@returns the expected length of the scan period (excluding retrace).
	*/
	inline int get_scan_period() {
		return standard_period_ - retrace_time_;
	}

	/*!
		@returns the expected length of a complete scan and retrace cycle.
	*/
	inline int get_standard_period() {
		return standard_period_;
	}

	/*!
		@returns the number of synchronisation events that have seemed surprising since the last time this method was called;
		a low number indicates good synchronisation.
	*/
	inline int get_and_reset_number_of_surprises() {
		const int result = number_of_surprises_;
		number_of_surprises_ = 0;
		return result;
	}

	/*!
		@returns `true` if a sync is expected soon or the time at which it was expected was recent.
	*/
	inline bool is_near_expected_sync() {
		return abs(counter_ - expected_next_sync_) < standard_period_ / 50;
	}

	private:
		const int standard_period_;		// the normal length of time between syncs
		const int retrace_time_;		// a constant indicating the amount of time it takes to perform a retrace
		const int sync_error_window_;	// a constant indicating the window either side of the next expected sync in which we'll accept other syncs

		int counter_ = 0;				// time since the _start_ of the last sync
		int counter_before_retrace_;	// the value of _counter immediately before retrace began
		int expected_next_sync_;		// our current expection of when the next sync will be encountered (which implies velocity)

		int number_of_surprises_ = 0;	// a count of the surprising syncs

		/*
			Implementation notes:

			Retrace takes a fixed amount of time and runs during [0, _retrace_time).

			For the current line, scan then occurs from [_retrace_time, _expected_next_sync), at which point
			retrace begins and the internal counter is reset.

			All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
			expected synchronisation time will cause a proportional adjustment in the expected time for the next
			synchronisation. Other synchronisation events are clamped as though they occurred in that range.
		*/
};

}
}

#endif /* Flywheel_hpp */
<commit_msg>Accounts for periods near an expected sync after a sync actually occurred.<commit_after>//
//  Flywheel.hpp
//  Clock Signal
//
//  Created by Thomas Harte on 11/02/2016.
//  Copyright 2016 Thomas Harte. All rights reserved.
//

#ifndef Flywheel_hpp
#define Flywheel_hpp

#include <cstdlib>
#include <cstdint>

namespace Outputs {
namespace CRT {

/*!
	Provides timing for a two-phase signal consisting of a retrace phase followed by a scan phase,
	announcing the start and end of retrace and providing the abiliy to read the current
	scanning position.

	The @c Flywheel will attempt to converge with timing implied by synchronisation pulses.
*/
struct Flywheel {
	/*!
		Constructs an instance of @c Flywheel.

		@param standard_period The expected amount of time between one synchronisation and the next.
		@param retrace_time The amount of time it takes to complete a retrace.
		@param sync_error_window The permitted deviation of sync timings from the norm.
	*/
	Flywheel(int standard_period, int retrace_time, int sync_error_window) :
		standard_period_(standard_period),
		retrace_time_(retrace_time),
		sync_error_window_(sync_error_window),
		counter_before_retrace_(standard_period - retrace_time),
		expected_next_sync_(standard_period) {}

	enum SyncEvent {
		/// Indicates that no synchronisation events will occur in the queried window.
		None,
		/// Indicates that the next synchronisation event will be a transition into retrce.
		StartRetrace,
		/// Indicates that the next synchronisation event will be a transition out of retrace.
		EndRetrace
	};
	/*!
		Asks the flywheel for the first synchronisation event that will occur in a given time period,
		indicating whether a synchronisation request occurred at the start of the query window.

		@param sync_is_requested @c true indicates that the flywheel should act as though having
		received a synchronisation request now; @c false indicates no such event was detected.

		@param cycles_to_run_for The number of cycles to look ahead.

		@param cycles_advanced After this method has completed, contains the amount of time until
		the returned synchronisation event.

		@returns The next synchronisation event.
	*/
	inline SyncEvent get_next_event_in_period(bool sync_is_requested, int cycles_to_run_for, int *cycles_advanced) {
		// do we recognise this hsync, thereby adjusting future time expectations?
		if(sync_is_requested) {
			if(counter_ < sync_error_window_ || counter_ > expected_next_sync_ - sync_error_window_) {
				const int time_now = (counter_ < sync_error_window_) ? expected_next_sync_ + counter_ : counter_;
				expected_next_sync_ = (3*expected_next_sync_ + time_now) >> 2;
			} else {
				++number_of_surprises_;

				if(counter_ < retrace_time_ + (expected_next_sync_ >> 1)) {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ + sync_error_window_) >> 2;
				} else {
					expected_next_sync_ = (3*expected_next_sync_ + standard_period_ - sync_error_window_) >> 2;
				}
			}
		}

		SyncEvent proposed_event = SyncEvent::None;
		int proposed_sync_time = cycles_to_run_for;

		// End an ongoing retrace?
		if(counter_ < retrace_time_ && counter_ + proposed_sync_time >= retrace_time_) {
			proposed_sync_time = retrace_time_ - counter_;
			proposed_event = SyncEvent::EndRetrace;
		}

		// Start a retrace?
		if(counter_ + proposed_sync_time >= expected_next_sync_) {
			proposed_sync_time = expected_next_sync_ - counter_;
			proposed_event = SyncEvent::StartRetrace;
		}

		*cycles_advanced = proposed_sync_time;
		return proposed_event;
	}

	/*!
		Advances a nominated amount of time, applying a previously returned synchronisation event
		at the end of that period.

		@param cycles_advanced The amount of time to run for.

		@param event The synchronisation event to apply after that period.
	*/
	inline void apply_event(int cycles_advanced, SyncEvent event) {
		// In debug builds, perform a sanity check for counter overflow.
#ifndef NDEBUG
		const int old_counter = counter_;
#endif
		counter_ += cycles_advanced;
#ifndef NDEBUG
		assert(old_counter <= counter_);
#endif

		switch(event) {
			default: return;
			case StartRetrace:
				counter_before_retrace_ = counter_ - retrace_time_;
				counter_ = 0;
			return;
		}
	}

	/*!
		Returns the current output position; while in retrace this will go down towards 0, while in scan
		it will go upward.

		@returns The current output position.
	*/
	inline int get_current_output_position() {
		if(counter_ < retrace_time_) {
			const int retrace_distance = int((int64_t(counter_) * int64_t(standard_period_)) / int64_t(retrace_time_));
			if(retrace_distance > counter_before_retrace_) return 0;
			return counter_before_retrace_ - retrace_distance;
		}

		return counter_ - retrace_time_;
	}

	/*!
		@returns the amount of time since retrace last began. Time then counts monotonically up from zero.
	*/
	inline int get_current_time() {
		return counter_;
	}

	/*!
		@returns whether the output is currently retracing.
	*/
	inline bool is_in_retrace() {
		return counter_ < retrace_time_;
	}

	/*!
		@returns the expected length of the scan period (excluding retrace).
	*/
	inline int get_scan_period() {
		return standard_period_ - retrace_time_;
	}

	/*!
		@returns the expected length of a complete scan and retrace cycle.
	*/
	inline int get_standard_period() {
		return standard_period_;
	}

	/*!
		@returns the number of synchronisation events that have seemed surprising since the last time this method was called;
		a low number indicates good synchronisation.
	*/
	inline int get_and_reset_number_of_surprises() {
		const int result = number_of_surprises_;
		number_of_surprises_ = 0;
		return result;
	}

	/*!
		@returns `true` if a sync is expected soon or if the time at which it was expected (or received) was recent.
	*/
	inline bool is_near_expected_sync() {
		return
			(counter_ < (standard_period_ / 100)) ||
			(counter_ >= expected_next_sync_ - (standard_period_ / 100));
	}

	private:
		const int standard_period_;		// the normal length of time between syncs
		const int retrace_time_;		// a constant indicating the amount of time it takes to perform a retrace
		const int sync_error_window_;	// a constant indicating the window either side of the next expected sync in which we'll accept other syncs

		int counter_ = 0;				// time since the _start_ of the last sync
		int counter_before_retrace_;	// the value of _counter immediately before retrace began
		int expected_next_sync_;		// our current expection of when the next sync will be encountered (which implies velocity)

		int number_of_surprises_ = 0;	// a count of the surprising syncs

		/*
			Implementation notes:

			Retrace takes a fixed amount of time and runs during [0, _retrace_time).

			For the current line, scan then occurs from [_retrace_time, _expected_next_sync), at which point
			retrace begins and the internal counter is reset.

			All synchronisation events that occur within (-_sync_error_window, _sync_error_window) of the
			expected synchronisation time will cause a proportional adjustment in the expected time for the next
			synchronisation. Other synchronisation events are clamped as though they occurred in that range.
		*/
};

}
}

#endif /* Flywheel_hpp */
<|endoftext|>