<commit_before>/*************************************************************************
 *
 *  $RCSfile: browserpage.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-16 12:01:26 $
 *
 *  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 EXPRESS 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 _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_

#ifndef _SV_TABPAGE_HXX
#include <vcl/tabpage.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_
#include "browserlistbox.hxx"
#endif

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

    //========================================================================
    //= OBrowserPage
    //========================================================================
    class OBrowserPage : public TabPage
    {
    private:
        OBrowserListBox     m_aListBox;

    protected:
        virtual void Resize();
        virtual void StateChanged(StateChangedType nType);

    public:
        OBrowserPage(Window* pParent, WinBits nWinStyle = 0);
        ~OBrowserPage();

        // #95343# -------------
        sal_Int32 getMinimumWidth();

              OBrowserListBox* getListBox();
        const OBrowserListBox* getListBox() const;
    };

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

#endif // _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.172); FILE MERGED 2005/09/05 13:00:01 rt 1.4.172.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: browserpage.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:03:36 $
 *
 *  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
 *
 ************************************************************************/

#ifndef _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_
#define _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_

#ifndef _SV_TABPAGE_HXX
#include <vcl/tabpage.hxx>
#endif
#ifndef _EXTENSIONS_PROPCTRLR_BROWSERLISTBOX_HXX_
#include "browserlistbox.hxx"
#endif

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

    //========================================================================
    //= OBrowserPage
    //========================================================================
    class OBrowserPage : public TabPage
    {
    private:
        OBrowserListBox     m_aListBox;

    protected:
        virtual void Resize();
        virtual void StateChanged(StateChangedType nType);

    public:
        OBrowserPage(Window* pParent, WinBits nWinStyle = 0);
        ~OBrowserPage();

        // #95343# -------------
        sal_Int32 getMinimumWidth();

              OBrowserListBox* getListBox();
        const OBrowserListBox* getListBox() const;
    };

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

#endif // _EXTENSIONS_PROPCTRLR_BROWSERPAGE_HXX_

<|endoftext|>


<commit_before>#include "board.hpp"

void DrawBoard()
{
	printf("   ");
	for (int i = 0; i < 8; i++) {
		putchar('a'+i);
		putchar(' ');
	}
	putchar('\n');
	for (int y = 0; y < 8; y++) {
		putchar('1'+y);
		putchar(' ');
		for (int x = 0; x < 8; x++) {
			putchar('|');
			putchar(CellsForDrawing[Board[y][x]]);
		}
		putchar('|');
		putchar('\n');
	}
}

<commit_msg>Improve board drawing, add modes<commit_after>#include "board.hpp"

void DrawBoard()
{
	const bool numbersOnTheRight = true;

	if (numbersOnTheRight) {
		printf("  ");
		for (int i = 0; i < 8; i++) {
			printf("%c ", 'a'+i);
		}
		putchar('\n');
		for (int y = 0; y < 8; y++) {
			putchar(' ');
			for (int x = 0; x < 8; x++) {
				putchar('|');
				putchar(CellsForDrawing[Board[y][x]]);
			}
			printf("| %c\n", '1'+y);
		}
	} else {
		printf("   ");
		for (int i = 0; i < 8; i++) {
			printf("%c ", 'a'+i);
		}
		putchar('\n');
		for (int y = 0; y < 8; y++) {
			printf("%c ", '1'+y);
			for (int x = 0; x < 8; x++) {
				putchar('|');
				putchar(CellsForDrawing[Board[y][x]]);
			}
			printf("|\n");
		}
	}
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: filtertracer.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: hr $ $Date: 2003-03-25 17:57:44 $
 *
 *  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 _FILTERTRACER_HXX
#include "filtertracer.hxx"
#endif
#ifndef _UTL_STREAM_WRAPPER_HXX_
#include <unotools/streamwrap.hxx>
#endif
#include <uno/mapping.hxx>
#ifndef _UNTOOLS_UCBSTREAMHELPER_HXX
#include <unotools/ucbstreamhelper.hxx>
#endif
// ----------------
// - FILTERTRACER -
// ----------------

rtl::OUString FilterTracer_getImplementationName()
    throw( NMSP_UNO::RuntimeException )
{
    return B2UCONST( "com.sun.star.util.FilterTracer" );
}
sal_Bool SAL_CALL FilterTracer_supportsService( const rtl::OUString& ServiceName )
    throw( NMSP_UNO::RuntimeException )
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.util.logging.Logger" ) );
}
SEQ( rtl::OUString ) SAL_CALL FilterTracer_getSupportedServiceNames()
    throw( NMSP_UNO::RuntimeException )
{
    SEQ( rtl::OUString ) aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] = B2UCONST( "com.sun.star.util.logging.Logger" );
    return aRet;
}

// -----------------------------------------------------------------------------

FilterTracer::FilterTracer( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) :
    xFact       ( rxMgr ),
    mpStream    ( NULL ),
    mnLogLevel  ( NMSP_LOGGING::LogLevel::ALL )
{
    REF( NMSP_UNO::XInterface ) xObj( rxMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.util.TextSearch" ) ) );
    mxTextSearch = REF( NMSP_UTIL::XTextSearch )( xObj, ::com::sun::star::uno::UNO_QUERY );
}
FilterTracer::~FilterTracer()
{
    if ( mpStream )
    {
        mxOutputStream = NULL;
        delete mpStream;
    }
}

// -----------------------------------------------------------------------------

// XInterface
void SAL_CALL FilterTracer::acquire() throw()
{
    OWeakObject::acquire();
}
void SAL_CALL FilterTracer::release() throw()
{
    OWeakObject::release();
}

// -----------------------------------------------------------------------------

// checks if the tokens of rFilter can be found in rString
sal_Bool FilterTracer::ImplFilter( const rtl::OUString& rFilter, const rtl::OUString& rString )
{
    sal_Bool bFilter = sal_False;
    if ( mxTextSearch.is() )
    {
        maSearchOptions.searchString = rFilter;
        mxTextSearch->setOptions( maSearchOptions );
        NMSP_UTIL::SearchResult aSearchResult = mxTextSearch->searchForward( rString, 0, rString.getLength() );
        bFilter = aSearchResult.subRegExpressions != 0;
    }
    return bFilter;
}

// -----------------------------------------------------------------------------

// XInitialization
void SAL_CALL FilterTracer::initialize( const SEQ( NMSP_UNO::Any )& aArguments )
    throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException )
{
    sal_Int32 i;
    SEQ( NMSP_BEANS::PropertyValue ) aParameter;
    for ( i = 0; i < aArguments.getLength(); i++ )
    {
        if ( aArguments[ i ] >>= aParameter )
            break;
    }
    for ( i = 0; i < aParameter.getLength(); i++ )
    {
        const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ];
        if ( rProp.Name.equalsAscii( "LogLevel" ) )
            rProp.Value >>= mnLogLevel;
        else if ( rProp.Name.equalsAscii( "ClassFilter" ) )
            rProp.Value >>= msClassFilter;
        else if ( rProp.Name.equalsAscii( "MethodFilter" ) )
            rProp.Value >>= msMethodFilter;
        else if ( rProp.Name.equalsAscii( "MessageFilter" ) )
            rProp.Value >>= msMessageFilter;
        else if ( rProp.Name.equalsAscii( "OutputStream" ) )
            rProp.Value >>= mxOutputStream;
        else if ( rProp.Name.equalsAscii( "URL" ) )
            rProp.Value >>= msURL;
    }

    // check if we have to create the XOutputStream
    if ( !mxOutputStream.is() && msURL.getLength() )
    {
        mpStream = ::utl::UcbStreamHelper::CreateStream( msURL, STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYNONE );
        if ( mpStream )
        {
            ::utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *mpStream );
            mxOutputStream = pHelper;
        }
    }
}

// -----------------------------------------------------------------------------

// XServiceInfo
rtl::OUString SAL_CALL FilterTracer::getImplementationName()
    throw( NMSP_UNO::RuntimeException )
{
    return FilterTracer_getImplementationName();
}
sal_Bool SAL_CALL FilterTracer::supportsService( const rtl::OUString& rServiceName )
    throw( NMSP_UNO::RuntimeException )
{
    return FilterTracer_supportsService( rServiceName );
}
SEQ( rtl::OUString ) SAL_CALL FilterTracer::getSupportedServiceNames()
    throw ( NMSP_UNO::RuntimeException )
{
    return FilterTracer_getSupportedServiceNames();
}

// -----------------------------------------------------------------------------

// XLogger
REF( NMSP_LOGGING::XLogger ) SAL_CALL  FilterTracer::getLogger( const rtl::OUString& rName )
     throw (::com::sun::star::uno::RuntimeException)
{
    REF( NMSP_LOGGING::XLogger ) xLog( this );
    return xLog;
}
sal_Int32 SAL_CALL FilterTracer::getLevel() throw (::com::sun::star::uno::RuntimeException)
{
    return mnLogLevel;
}
rtl::OUString SAL_CALL FilterTracer::getName() throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString aName;
    return aName;
}
sal_Bool SAL_CALL FilterTracer::isLoggable( sal_Int32 nLevel )
     throw (::com::sun::star::uno::RuntimeException)
{
    return mnLogLevel <= nLevel;
}
void SAL_CALL FilterTracer::logp( sal_Int32 nLevel, const rtl::OUString& rSourceClass,
        const rtl::OUString& rSourceMethod, const rtl::OUString& rMessage )
     throw (::com::sun::star::uno::RuntimeException)
{
    if ( mxOutputStream.is() )
    {
        if ( ! ( ImplFilter( msClassFilter, rSourceClass ) || ImplFilter( msMethodFilter, rSourceMethod )
            || ImplFilter( msMessageFilter, rMessage ) ) )
        {
            rtl::OString sClass( rtl::OUStringToOString( rSourceClass, RTL_TEXTENCODING_UTF8 ) );
            rtl::OString sMethod( rtl::OUStringToOString( rSourceMethod, RTL_TEXTENCODING_UTF8 ) );
            rtl::OString sMessage( rtl::OUStringToOString( rMessage, RTL_TEXTENCODING_UTF8 ) );
            try
            {
                SEQ( sal_Int8 ) aData( sClass.getLength() + sMethod.getLength() + sMessage.getLength() );
                sal_Int8* pPtr = aData.getArray();
                memcpy( pPtr, sClass.getStr(), sClass.getLength() );
                pPtr += sClass.getLength();
                memcpy( pPtr, sMethod.getStr(), sMethod.getLength() );
                pPtr += sMethod.getLength();
                memcpy( pPtr, sMessage.getStr(), sMessage.getLength() );
                pPtr += sMessage.getLength();
                mxOutputStream->writeBytes( aData );
            }
            catch ( ... )
            {

            }
        }
    }
}

// -----------------------------------------------------------------------------

// XTextSearch
void SAL_CALL  FilterTracer::setOptions( const NMSP_UTIL::SearchOptions& rSearchOptions )
    throw (::com::sun::star::uno::RuntimeException)
{
    maSearchOptions = rSearchOptions;
}

// -----------------------------------------------------------------------------

NMSP_UTIL::SearchResult SAL_CALL FilterTracer::searchForward( const rtl::OUString& rSearchStr,
        sal_Int32 nStartPos, sal_Int32 nEndPos ) throw (::com::sun::star::uno::RuntimeException)
{
    NMSP_UTIL::SearchResult nSearchResult;
    if ( mxTextSearch.is() )
        mxTextSearch->searchForward( rSearchStr, nStartPos, nEndPos );
    return nSearchResult;
}

// -----------------------------------------------------------------------------

NMSP_UTIL::SearchResult SAL_CALL FilterTracer::searchBackward( const rtl::OUString& rSearchStr,
        sal_Int32 nStartPos, sal_Int32 nEndPos ) throw (::com::sun::star::uno::RuntimeException)
{
    NMSP_UTIL::SearchResult nSearchResult;
    if ( mxTextSearch.is() )
        mxTextSearch->searchBackward( rSearchStr, nStartPos, nEndPos );
    return nSearchResult;
}

<commit_msg>INTEGRATION: CWS filtertracer01 (1.2.64); FILE MERGED 2003/07/11 13:53:00 sj 1.2.64.1: supporting DocumentHandler<commit_after>/*************************************************************************
 *
 *  $RCSfile: filtertracer.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2003-08-07 15:22:38 $
 *
 *  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 _FILTERTRACER_HXX
#include "filtertracer.hxx"
#endif
#include <uno/mapping.hxx>
#ifndef _UTL_STREAM_WRAPPER_HXX_
#include <unotools/streamwrap.hxx>
#endif
#ifndef _UNTOOLS_UCBSTREAMHELPER_HXX
#include <unotools/ucbstreamhelper.hxx>
#endif
// ----------------
// - FILTERTRACER -
// ----------------

rtl::OUString FilterTracer_getImplementationName()
    throw( NMSP_UNO::RuntimeException )
{
    return B2UCONST( "com.sun.star.util.FilterTracer" );
}
sal_Bool SAL_CALL FilterTracer_supportsService( const rtl::OUString& ServiceName )
    throw( NMSP_UNO::RuntimeException )
{
    return ServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "com.sun.star.util.logging.Logger" ) );
}
SEQ( rtl::OUString ) SAL_CALL FilterTracer_getSupportedServiceNames()
    throw( NMSP_UNO::RuntimeException )
{
    SEQ( rtl::OUString ) aRet(1);
    rtl::OUString* pArray = aRet.getArray();
    pArray[0] = B2UCONST( "com.sun.star.util.logging.Logger" );
    return aRet;
}

// -----------------------------------------------------------------------------

FilterTracer::FilterTracer( const REF( NMSP_LANG::XMultiServiceFactory )& rxMgr ) :
    xFact       ( rxMgr ),
    mpStream    ( NULL ),
    mnLogLevel  ( NMSP_LOGGING::LogLevel::ALL )
{
    REF( NMSP_UNO::XInterface ) xObj( rxMgr->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.util.TextSearch" ) ) );
    mxTextSearch = REF( NMSP_UTIL::XTextSearch )( xObj, ::com::sun::star::uno::UNO_QUERY );
}
FilterTracer::~FilterTracer()
{
    if ( mpStream )
    {
        mxOutputStream = NULL;
        delete mpStream;
    }
}

// -----------------------------------------------------------------------------

// XInterface
void SAL_CALL FilterTracer::acquire() throw()
{
    OWeakObject::acquire();
}
void SAL_CALL FilterTracer::release() throw()
{
    OWeakObject::release();
}

// -----------------------------------------------------------------------------

// checks if the tokens of rFilter can be found in rString
sal_Bool FilterTracer::ImplFilter( const rtl::OUString& rFilter, const rtl::OUString& rString )
{
    sal_Bool bFilter = sal_False;
    if ( mxTextSearch.is() )
    {
        maSearchOptions.searchString = rFilter;
        mxTextSearch->setOptions( maSearchOptions );
        NMSP_UTIL::SearchResult aSearchResult = mxTextSearch->searchForward( rString, 0, rString.getLength() );
        bFilter = aSearchResult.subRegExpressions != 0;
    }
    return bFilter;
}

// -----------------------------------------------------------------------------

// XInitialization
void SAL_CALL FilterTracer::initialize( const SEQ( NMSP_UNO::Any )& aArguments )
    throw ( NMSP_UNO::Exception, NMSP_UNO::RuntimeException )
{
    sal_Int32 i;
    SEQ( NMSP_BEANS::PropertyValue ) aParameter;
    for ( i = 0; i < aArguments.getLength(); i++ )
    {
        if ( aArguments[ i ] >>= aParameter )
            break;
    }
    for ( i = 0; i < aParameter.getLength(); i++ )
    {
        const NMSP_BEANS::PropertyValue& rProp = aParameter[ i ];
        if ( rProp.Name.equalsAscii( "LogLevel" ) )
            rProp.Value >>= mnLogLevel;
        else if ( rProp.Name.equalsAscii( "ClassFilter" ) )
            rProp.Value >>= msClassFilter;
        else if ( rProp.Name.equalsAscii( "MethodFilter" ) )
            rProp.Value >>= msMethodFilter;
        else if ( rProp.Name.equalsAscii( "MessageFilter" ) )
            rProp.Value >>= msMessageFilter;
        else if ( rProp.Name.equalsAscii( "OutputStream" ) )
            rProp.Value >>= mxOutputStream;
        else if ( rProp.Name.equalsAscii( "URL" ) )
            rProp.Value >>= msURL;
        else if ( rProp.Name.equalsAscii( "DocumentHandler" ) )
            rProp.Value >>= mxDocumentHandler;
    }

    // check if we have to create the XOutputStream
    if ( !mxOutputStream.is() && msURL.getLength() )
    {
        mpStream = ::utl::UcbStreamHelper::CreateStream( msURL, STREAM_WRITE | STREAM_TRUNC | STREAM_SHARE_DENYNONE );
        if ( mpStream )
        {
            ::utl::OOutputStreamWrapper* pHelper = new ::utl::OOutputStreamWrapper( *mpStream );
            mxOutputStream = pHelper;
        }
    }
}

// -----------------------------------------------------------------------------

// XServiceInfo
rtl::OUString SAL_CALL FilterTracer::getImplementationName()
    throw( NMSP_UNO::RuntimeException )
{
    return FilterTracer_getImplementationName();
}
sal_Bool SAL_CALL FilterTracer::supportsService( const rtl::OUString& rServiceName )
    throw( NMSP_UNO::RuntimeException )
{
    return FilterTracer_supportsService( rServiceName );
}
SEQ( rtl::OUString ) SAL_CALL FilterTracer::getSupportedServiceNames()
    throw ( NMSP_UNO::RuntimeException )
{
    return FilterTracer_getSupportedServiceNames();
}

// -----------------------------------------------------------------------------

// XLogger
REF( NMSP_LOGGING::XLogger ) SAL_CALL  FilterTracer::getLogger( const rtl::OUString& rName )
     throw (::com::sun::star::uno::RuntimeException)
{
    REF( NMSP_LOGGING::XLogger ) xLog( this );
    return xLog;
}
sal_Int32 SAL_CALL FilterTracer::getLevel() throw (::com::sun::star::uno::RuntimeException)
{
    return mnLogLevel;
}
rtl::OUString SAL_CALL FilterTracer::getName() throw (::com::sun::star::uno::RuntimeException)
{
    rtl::OUString aName;
    return aName;
}
sal_Bool SAL_CALL FilterTracer::isLoggable( sal_Int32 nLevel )
     throw (::com::sun::star::uno::RuntimeException)
{
    return mnLogLevel <= nLevel;
}
void SAL_CALL FilterTracer::logp( sal_Int32 nLevel, const rtl::OUString& rSourceClass,
        const rtl::OUString& rSourceMethod, const rtl::OUString& rMessage )
     throw (::com::sun::star::uno::RuntimeException)
{
    if ( mxOutputStream.is() || mxDocumentHandler.is() )
    {
        if ( ! ( ImplFilter( msClassFilter, rSourceClass ) || ImplFilter( msMethodFilter, rSourceMethod )
            || ImplFilter( msMessageFilter, rMessage ) ) )
        {
            rtl::OString sClass( rtl::OUStringToOString( rSourceClass, RTL_TEXTENCODING_UTF8 ) );
            rtl::OString sMethod( rtl::OUStringToOString( rSourceMethod, RTL_TEXTENCODING_UTF8 ) );
            rtl::OString sMessage( rtl::OUStringToOString( rMessage, RTL_TEXTENCODING_UTF8 ) );
            try
            {
                SEQ( sal_Int8 ) aData( sClass.getLength() + sMethod.getLength() + sMessage.getLength() );
                sal_Int8* pPtr = aData.getArray();
                memcpy( pPtr, sClass.getStr(), sClass.getLength() );
                pPtr += sClass.getLength();
                memcpy( pPtr, sMethod.getStr(), sMethod.getLength() );
                pPtr += sMethod.getLength();
                memcpy( pPtr, sMessage.getStr(), sMessage.getLength() );
                pPtr += sMessage.getLength();
                if ( mxOutputStream.is() )
                    mxOutputStream->writeBytes( aData );
                if ( mxDocumentHandler.is() )
                    mxDocumentHandler->characters( ::rtl::OUString( (sal_Char*)aData.getArray(), aData.getLength(), RTL_TEXTENCODING_UTF8 ) );
            }
            catch ( ... )
            {

            }
        }
    }
}

// -----------------------------------------------------------------------------

// XTextSearch
void SAL_CALL  FilterTracer::setOptions( const NMSP_UTIL::SearchOptions& rSearchOptions )
    throw (::com::sun::star::uno::RuntimeException)
{
    maSearchOptions = rSearchOptions;
}

// -----------------------------------------------------------------------------

NMSP_UTIL::SearchResult SAL_CALL FilterTracer::searchForward( const rtl::OUString& rSearchStr,
        sal_Int32 nStartPos, sal_Int32 nEndPos ) throw (::com::sun::star::uno::RuntimeException)
{
    NMSP_UTIL::SearchResult nSearchResult;
    if ( mxTextSearch.is() )
        mxTextSearch->searchForward( rSearchStr, nStartPos, nEndPos );
    return nSearchResult;
}

// -----------------------------------------------------------------------------

NMSP_UTIL::SearchResult SAL_CALL FilterTracer::searchBackward( const rtl::OUString& rSearchStr,
        sal_Int32 nStartPos, sal_Int32 nEndPos ) throw (::com::sun::star::uno::RuntimeException)
{
    NMSP_UTIL::SearchResult nSearchResult;
    if ( mxTextSearch.is() )
        mxTextSearch->searchBackward( rSearchStr, nStartPos, nEndPos );
    return nSearchResult;
}

<|endoftext|>


<commit_before>// @(#)root/net:$Name:  $:$Id: TCache.cxx,v 1.2 2001/01/15 23:49:11 rdm Exp $
// Author: Fons Rademakers   13/01/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TCache                                                               //
//                                                                      //
// A caching system to speed up network I/O, i.e. when there is         //
// no operating system caching support (like the buffer cache for       //
// local disk I/O). The cache makes sure that every I/O is done with    //
// a (large) fixed length buffer thereby avoiding many small I/O's.     //
// The default page size is 512KB. The cache size is not very important //
// when writing sequentially a file, since the pages will not be        //
// reused. In that case use a small cache containing 10 to 20 pages.    //
// In case a file is used for random-access the cache size should be    //
// taken much larger to avoid re-reading pages over the network.        //
// Notice that the TTree's have their own caching mechanism (see        //
// TTree::SetMaxVirtualSize()), so when using mainly TTree's with large //
// basket buffers the cache can be kept quite small.                    //
// Currently the TCache system is used by the classes TNetFile,         //
// TRFIOFile and TWebFile.                                              //
//                                                                      //
// Extra improvement would be to run the Free() process in a separate   //
// thread. Possible flush parameters:                                   //
// nfract  25   fraction of dirty buffers above which the flush process //
//              is activated                                            //
// ndirty  500  maximum number of buffer block which may be written     //
//              during a flush                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TCache.h"
#include "TSortedList.h"
#include "TFile.h"

ClassImp(TCache)

//______________________________________________________________________________
TCache::TCache(Int_t maxCacheSize, TFile *file, Int_t pageSize)
{
   // Create a file cache. Mainly useful for remote files like TNetFile,
   // TWebFile and TRFIOFile where the local OS is not doing any caching.
   // The maxCacheSize is in MBytes and the pageSize is in bytes (default
   // being kDfltPageSize).

   if (!file) {
      Error("TCache", "no file specified");
      MakeZombie();
      return;
   }

   fFile      = file;
   fEOF       = fFile->GetEND();
   fHighWater = maxCacheSize * 1024 * 1024;
   fLowWater  = fHighWater * kDfltLowLevel / 100;
   fLowLevel  = kDfltLowLevel;
   fRecursive = kFALSE;
   SetPageSize(pageSize);

   fCache = new TCacheList(Int_t(fHighWater/fPageSize/3));
   fNew   = new TSortedList;
   fFree  = new TList;
   fCache->SetOwner();
   fFree->SetOwner();
}

//______________________________________________________________________________
TCache::~TCache()
{
   // Clean up cache.

   delete fCache;
   delete fNew;
   delete fFree;
}

//______________________________________________________________________________
void TCache::SetPageSize(Int_t size)
{
   // Make sure the page size is a power of two, with a minimum of 4096.

   if (size < 4096) size = 4096;

   for (int i = 0; i < int(sizeof(size)*8); i++)
      if ((size >> i) == 1) {
         fDiv = i;
         break;
      }

   fPageSize = 1 << fDiv;
}

//______________________________________________________________________________
TCache::TPage *TCache::ReadPage(Seek_t offset)
{
   // Read the page starting at offset in the cache and return the
   // page object. If there are no more free pages free pages up
   // to the low water mark. The freed pages are the least recently
   // used pages (lru) which are at the head of the fCache hash list.
   // Returns 0 in case of error.

   fRecursive = kTRUE;

   // check if there is a free page object in the free list and use that
   if (fFree->GetSize() > 0) {
      TPage *p = (TPage*) fFree->First();
      fFile->Seek(offset);
      Int_t len = offset + fPageSize > fEOF ? Int_t(fEOF - offset) : fPageSize;
      if (len < 0) len = 0;
      if (len && fFile->ReadBuffer(p->Data(), len)) {
         fRecursive = kFALSE;
         return 0;
      }
      p->fOffset = offset;
      p->fSize   = len;
      fFree->Remove(p);
      fCache->Add(p);
      fRecursive = kFALSE;
      return p;
   }

   // if cache is not full, create new page and use it
   if (ULong_t(fCache->GetSize() * fPageSize) < fHighWater) {
      char *data = new char[fPageSize];
      fFile->Seek(offset);
      Int_t len = offset + fPageSize > fEOF ? Int_t(fEOF - offset) : fPageSize;
      if (len < 0) len = 0;
      if (len && fFile->ReadBuffer(data, len)) {
         fRecursive = kFALSE;
         return 0;
      }
      TPage *p = new TPage(offset, data, len);
      fCache->Add(p);
      fRecursive = kFALSE;
      return p;
   }

   // if we come here there are no free pages and the cache is full, free
   // pages up to low water mark
   if (Free(fLowWater) < 0) {
      fRecursive = kFALSE;
      return 0;
   }

   return ReadPage(offset);
}

//______________________________________________________________________________
Int_t TCache::ReadBuffer(Seek_t offset, char *buf, Int_t len)
{
   // Return in buf len bytes starting at offset. Returns < 0 in
   // case of error, 0 in case ReadBuffer() was recursively called
   // via ReadPage() and 1 in case of success.

   if (fRecursive) return 0;

   // Find in which page offset is located
   Seek_t pageoffset = (offset >> fDiv) << fDiv;  // offset & ~(fPageSize-1)
   Int_t  begin = Int_t(offset & (fPageSize-1));
   Seek_t boff  = 0;

   do {
      Int_t blen = begin+len>fPageSize ? fPageSize-begin : len;
      TPage t(pageoffset, 0, 0);
      TPage *p = (TPage*) fCache->FindObject(&t);
      if (p) {
         // found page in cache, copy to buf
         memcpy(buf+boff, p->Data()+begin, blen);
         fCache->PageUsed(p);
      } else {
         // read page in cache and copy to buf
         p = ReadPage(pageoffset);
         if (p)
            memcpy(buf+boff, p->Data()+begin, blen);
         else
            return -1;
      }
      boff       += blen;
      len        -= blen;
      pageoffset += fPageSize;
      begin       = 0;
   } while (len > 0);

   return 1;
}

//______________________________________________________________________________
Int_t TCache::WritePage(TPage *page)
{
   // Write dirty page to file. Returns -1 in case of error.

   fRecursive = kTRUE;

   page->SetBit(TPage::kLocked);

   fFile->Seek(page->Offset());
   if (fFile->WriteBuffer(page->Data(), page->Size())) {
      page->ResetBit(TPage::kLocked);
      fRecursive = kFALSE;
      return -1;
   }

   if (page->Offset() + page->Size() > fEOF)
      fEOF = page->Offset() + page->Size();

   page->ResetBit(TPage::kDirty);
   page->ResetBit(TPage::kLocked);

   fRecursive = kFALSE;

   return 0;
}

//______________________________________________________________________________
Int_t TCache::WriteBuffer(Seek_t offset, const char *buf, Int_t len)
{
   // Write a buffer to the cache. Returns < 0 in case of error, 0 in
   // case WriteBuffer() was recursively called via WritePage() and 1
   // in case of success.

   if (fRecursive) return 0;

   // Find in which page offset is located
   Seek_t pageoffset = (offset >> fDiv) << fDiv;  // offset & ~(fPageSize-1)
   Int_t  begin = Int_t(offset & (fPageSize-1));
   Seek_t boff  = 0;

   do {
      Int_t blen = begin+len>fPageSize ? fPageSize-begin : len;
      TPage t(pageoffset, 0, 0);
      TPage *p = (TPage*) fCache->FindObject(&t);
      if (p) {
         // found page in cache, copy buf to it
         memcpy(p->Data()+begin, buf+boff, blen);
         if (p->fSize < begin+blen) {
            p->fSize = begin+blen;
            if (!fNew->Contains(p))
               fNew->Add(p);
         }
         p->SetBit(TPage::kDirty);
         fCache->PageUsed(p);
      } else {
         // read page in cache and copy buf to it
         p = ReadPage(pageoffset);
         if (p) {
            memcpy(p->Data()+begin, buf+boff, blen);
            if (p->fSize < begin+blen) {
               p->fSize = begin+blen;
               if (!fNew->Contains(p))
                  fNew->Add(p);
            }
            p->SetBit(TPage::kDirty);
         } else
            return -1;
      }
      boff       += blen;
      len        -= blen;
      pageoffset += fPageSize;
      begin       = 0;
   } while (len > 0);

   return 1;
}

//______________________________________________________________________________
Int_t TCache::Free(ULong_t upto)
{
   // Free pages so that specified number of bytes remains in the cache.
   // Dirty pages are written to file. Returns < 0 in case of error
   // (typically when there was an error writing a dirty page).

   Int_t err;
   if ((err = FlushNew()) < 0)
      return err;

   while (ULong_t(fCache->GetSize() * fPageSize) > upto) {
      TPage *p = (TPage*) fCache->First();
      if (p->TestBit(TPage::kDirty)) {
         if ((err = WritePage(p)) < 0)
            return err;
      }
      fCache->Remove(p);
      fFree->Add(p);
   }
   return 0;
}

//______________________________________________________________________________
Int_t TCache::FlushList(TList *list)
{
   // Flush all dirty pages in the specified list to file. Return < 0 in
   // case of error (typically when there was an error writing a dirty page).

   TIter next(list);
   TPage *p;
   while ((p = (TPage*) next())) {
      if (p->TestBit(TPage::kDirty)) {
         Int_t err;
         if ((err = WritePage(p)) < 0)
            return err;
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t TCache::Flush()
{
   // Flush all dirty pages to file. Return < 0 in case of error
   // (typically when there was an error writing a dirty page).

   Int_t err;
   if ((err = FlushNew()) < 0)
      return err;
   if ((err = FlushList(fCache)) < 0)
      return err;

   return 0;
}

//______________________________________________________________________________
Int_t TCache::FlushNew()
{
   // Flush all new pages to file. New pages are pages in the fNew list.
   // When a page is in this list it means that this page extends the file
   // (i.e. is adds new pages to the file). The issue with new pages is that
   // they need to be flushed in the right order. One can not write at an
   // offset past the EOF. Therefore the new pages are put in a sorted
   // list and then written in ascending fOffset order.

   Int_t err;
   if ((err = FlushList(fNew)) < 0)
      return err;

   fNew->Clear();

   return 0;
}

//______________________________________________________________________________
Int_t TCache::Resize(Int_t maxCacheSize)
{
   // Resize the cache (either increase or decrease the size). Returns the
   // previous cache size or -1 in case of error. Input and output is in MB's.
   // Minimum cache size is 1 MB.

   if (maxCacheSize < 1) maxCacheSize = 1;

   ULong_t newSize = maxCacheSize * 1024 * 1024;
   Int_t   oldSize = Int_t(fHighWater / 1024 / 1024);

   if (newSize == fHighWater)
      return maxCacheSize;

   else if (newSize < fHighWater) {
      ULong_t inUse = (fCache->GetSize() + fFree->GetSize()) * fPageSize;
      if (inUse > newSize) {
         // first free active cache to not contain more than newSize,
         // then delete free pages up to desired new limit
         if (ULong_t(fCache->GetSize() * fPageSize) > newSize) {
            if (Free(newSize) < 0) {
               Error("Resize", "error freeing pages");
               return -1;
            }
            fFree->Delete();
         } else {
            while (inUse > newSize) {
               TPage *p = (TPage*) fFree->First();
               if (!p) break;
               fFree->Remove(p);
               delete p;
               inUse -= fPageSize;
            }
         }
      }
   }
   fHighWater = newSize;
   fLowWater  = fHighWater * fLowLevel / 100;
   return oldSize;
}

//______________________________________________________________________________
Int_t TCache::GetActiveCacheSize() const
{
   // Get size of all allocated cache pages (in use and free pages).

   return Int_t(((fCache->GetSize()+fFree->GetSize())*fPageSize)/1024/1024);
}

//______________________________________________________________________________
void TCache::SetLowLevel(Int_t percentOfHigh)
{
   // Set the low water level. This is in percent of the maxCacheSize.
   // When the cache is full it will be freed up to percentOfHigh. The
   // default is kDfltLowLevel=70%.

   fLowLevel = percentOfHigh;
   fLowWater = fHighWater * fLowLevel / 100;
}
<commit_msg>use TFile::GetSize() to get the current file size.<commit_after>// @(#)root/net:$Name:  $:$Id: TCache.cxx,v 1.3 2001/01/16 17:23:26 rdm Exp $
// Author: Fons Rademakers   13/01/2001

/*************************************************************************
 * Copyright (C) 1995-2001, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TCache                                                               //
//                                                                      //
// A caching system to speed up network I/O, i.e. when there is         //
// no operating system caching support (like the buffer cache for       //
// local disk I/O). The cache makes sure that every I/O is done with    //
// a (large) fixed length buffer thereby avoiding many small I/O's.     //
// The default page size is 512KB. The cache size is not very important //
// when writing sequentially a file, since the pages will not be        //
// reused. In that case use a small cache containing 10 to 20 pages.    //
// In case a file is used for random-access the cache size should be    //
// taken much larger to avoid re-reading pages over the network.        //
// Notice that the TTree's have their own caching mechanism (see        //
// TTree::SetMaxVirtualSize()), so when using mainly TTree's with large //
// basket buffers the cache can be kept quite small.                    //
// Currently the TCache system is used by the classes TNetFile,         //
// TRFIOFile and TWebFile.                                              //
//                                                                      //
// Extra improvement would be to run the Free() process in a separate   //
// thread. Possible flush parameters:                                   //
// nfract  25   fraction of dirty buffers above which the flush process //
//              is activated                                            //
// ndirty  500  maximum number of buffer block which may be written     //
//              during a flush                                          //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TCache.h"
#include "TSortedList.h"
#include "TFile.h"

ClassImp(TCache)

//______________________________________________________________________________
TCache::TCache(Int_t maxCacheSize, TFile *file, Int_t pageSize)
{
   // Create a file cache. Mainly useful for remote files like TNetFile,
   // TWebFile and TRFIOFile where the local OS is not doing any caching.
   // The maxCacheSize is in MBytes and the pageSize is in bytes (default
   // being kDfltPageSize).

   if (!file) {
      Error("TCache", "no file specified");
      MakeZombie();
      return;
   }

   fFile      = file;
   fEOF       = fFile->GetSize();              // get initial file size
   fHighWater = maxCacheSize * 1024 * 1024;
   fLowWater  = fHighWater * kDfltLowLevel / 100;
   fLowLevel  = kDfltLowLevel;
   fRecursive = kFALSE;
   SetPageSize(pageSize);

   fCache = new TCacheList(Int_t(fHighWater/fPageSize/3));
   fNew   = new TSortedList;
   fFree  = new TList;
   fCache->SetOwner();
   fFree->SetOwner();
}

//______________________________________________________________________________
TCache::~TCache()
{
   // Clean up cache.

   delete fCache;
   delete fNew;
   delete fFree;
}

//______________________________________________________________________________
void TCache::SetPageSize(Int_t size)
{
   // Make sure the page size is a power of two, with a minimum of 4096.

   if (size < 4096) size = 4096;

   for (int i = 0; i < int(sizeof(size)*8); i++)
      if ((size >> i) == 1) {
         fDiv = i;
         break;
      }

   fPageSize = 1 << fDiv;
}

//______________________________________________________________________________
TCache::TPage *TCache::ReadPage(Seek_t offset)
{
   // Read the page starting at offset in the cache and return the
   // page object. If there are no more free pages free pages up
   // to the low water mark. The freed pages are the least recently
   // used pages (lru) which are at the head of the fCache hash list.
   // Returns 0 in case of error.

   fRecursive = kTRUE;

   // check if there is a free page object in the free list and use that
   if (fFree->GetSize() > 0) {
      TPage *p = (TPage*) fFree->First();
      fFile->Seek(offset);
      Int_t len = offset + fPageSize > fEOF ? Int_t(fEOF - offset) : fPageSize;
      if (len < 0) len = 0;
      if (len && fFile->ReadBuffer(p->Data(), len)) {
         fRecursive = kFALSE;
         return 0;
      }
      p->fOffset = offset;
      p->fSize   = len;
      fFree->Remove(p);
      fCache->Add(p);
      fRecursive = kFALSE;
      return p;
   }

   // if cache is not full, create new page and use it
   if (ULong_t(fCache->GetSize() * fPageSize) < fHighWater) {
      char *data = new char[fPageSize];
      fFile->Seek(offset);
      Int_t len = offset + fPageSize > fEOF ? Int_t(fEOF - offset) : fPageSize;
      if (len < 0) len = 0;
      if (len && fFile->ReadBuffer(data, len)) {
         fRecursive = kFALSE;
         return 0;
      }
      TPage *p = new TPage(offset, data, len);
      fCache->Add(p);
      fRecursive = kFALSE;
      return p;
   }

   // if we come here there are no free pages and the cache is full, free
   // pages up to low water mark
   if (Free(fLowWater) < 0) {
      fRecursive = kFALSE;
      return 0;
   }

   return ReadPage(offset);
}

//______________________________________________________________________________
Int_t TCache::ReadBuffer(Seek_t offset, char *buf, Int_t len)
{
   // Return in buf len bytes starting at offset. Returns < 0 in
   // case of error, 0 in case ReadBuffer() was recursively called
   // via ReadPage() and 1 in case of success.

   if (fRecursive) return 0;

   // Find in which page offset is located
   Seek_t pageoffset = (offset >> fDiv) << fDiv;  // offset & ~(fPageSize-1)
   Int_t  begin = Int_t(offset & (fPageSize-1));
   Seek_t boff  = 0;

   do {
      Int_t blen = begin+len>fPageSize ? fPageSize-begin : len;
      TPage t(pageoffset, 0, 0);
      TPage *p = (TPage*) fCache->FindObject(&t);
      if (p) {
         // found page in cache, copy to buf
         memcpy(buf+boff, p->Data()+begin, blen);
         fCache->PageUsed(p);
      } else {
         // read page in cache and copy to buf
         p = ReadPage(pageoffset);
         if (p)
            memcpy(buf+boff, p->Data()+begin, blen);
         else
            return -1;
      }
      boff       += blen;
      len        -= blen;
      pageoffset += fPageSize;
      begin       = 0;
   } while (len > 0);

   return 1;
}

//______________________________________________________________________________
Int_t TCache::WritePage(TPage *page)
{
   // Write dirty page to file. Returns -1 in case of error.

   fRecursive = kTRUE;

   page->SetBit(TPage::kLocked);

   fFile->Seek(page->Offset());
   if (fFile->WriteBuffer(page->Data(), page->Size())) {
      page->ResetBit(TPage::kLocked);
      fRecursive = kFALSE;
      return -1;
   }

   if (page->Offset() + page->Size() > fEOF)
      fEOF = page->Offset() + page->Size();

   page->ResetBit(TPage::kDirty);
   page->ResetBit(TPage::kLocked);

   fRecursive = kFALSE;

   return 0;
}

//______________________________________________________________________________
Int_t TCache::WriteBuffer(Seek_t offset, const char *buf, Int_t len)
{
   // Write a buffer to the cache. Returns < 0 in case of error, 0 in
   // case WriteBuffer() was recursively called via WritePage() and 1
   // in case of success.

   if (fRecursive) return 0;

   // Find in which page offset is located
   Seek_t pageoffset = (offset >> fDiv) << fDiv;  // offset & ~(fPageSize-1)
   Int_t  begin = Int_t(offset & (fPageSize-1));
   Seek_t boff  = 0;

   do {
      Int_t blen = begin+len>fPageSize ? fPageSize-begin : len;
      TPage t(pageoffset, 0, 0);
      TPage *p = (TPage*) fCache->FindObject(&t);
      if (p) {
         // found page in cache, copy buf to it
         memcpy(p->Data()+begin, buf+boff, blen);
         if (p->fSize < begin+blen) {
            p->fSize = begin+blen;
            if (!fNew->Contains(p))
               fNew->Add(p);
         }
         p->SetBit(TPage::kDirty);
         fCache->PageUsed(p);
      } else {
         // read page in cache and copy buf to it
         p = ReadPage(pageoffset);
         if (p) {
            memcpy(p->Data()+begin, buf+boff, blen);
            if (p->fSize < begin+blen) {
               p->fSize = begin+blen;
               if (!fNew->Contains(p))
                  fNew->Add(p);
            }
            p->SetBit(TPage::kDirty);
         } else
            return -1;
      }
      boff       += blen;
      len        -= blen;
      pageoffset += fPageSize;
      begin       = 0;
   } while (len > 0);

   return 1;
}

//______________________________________________________________________________
Int_t TCache::Free(ULong_t upto)
{
   // Free pages so that specified number of bytes remains in the cache.
   // Dirty pages are written to file. Returns < 0 in case of error
   // (typically when there was an error writing a dirty page).

   Int_t err;
   if ((err = FlushNew()) < 0)
      return err;

   while (ULong_t(fCache->GetSize() * fPageSize) > upto) {
      TPage *p = (TPage*) fCache->First();
      if (p->TestBit(TPage::kDirty)) {
         if ((err = WritePage(p)) < 0)
            return err;
      }
      fCache->Remove(p);
      fFree->Add(p);
   }
   return 0;
}

//______________________________________________________________________________
Int_t TCache::FlushList(TList *list)
{
   // Flush all dirty pages in the specified list to file. Return < 0 in
   // case of error (typically when there was an error writing a dirty page).

   TIter next(list);
   TPage *p;
   while ((p = (TPage*) next())) {
      if (p->TestBit(TPage::kDirty)) {
         Int_t err;
         if ((err = WritePage(p)) < 0)
            return err;
      }
   }
   return 0;
}

//______________________________________________________________________________
Int_t TCache::Flush()
{
   // Flush all dirty pages to file. Return < 0 in case of error
   // (typically when there was an error writing a dirty page).

   Int_t err;
   if ((err = FlushNew()) < 0)
      return err;
   if ((err = FlushList(fCache)) < 0)
      return err;

   return 0;
}

//______________________________________________________________________________
Int_t TCache::FlushNew()
{
   // Flush all new pages to file. New pages are pages in the fNew list.
   // When a page is in this list it means that this page extends the file
   // (i.e. is adds new pages to the file). The issue with new pages is that
   // they need to be flushed in the right order. One can not write at an
   // offset past the EOF. Therefore the new pages are put in a sorted
   // list and then written in ascending fOffset order.

   Int_t err;
   if ((err = FlushList(fNew)) < 0)
      return err;

   fNew->Clear();

   return 0;
}

//______________________________________________________________________________
Int_t TCache::Resize(Int_t maxCacheSize)
{
   // Resize the cache (either increase or decrease the size). Returns the
   // previous cache size or -1 in case of error. Input and output is in MB's.
   // Minimum cache size is 1 MB.

   if (maxCacheSize < 1) maxCacheSize = 1;

   ULong_t newSize = maxCacheSize * 1024 * 1024;
   Int_t   oldSize = Int_t(fHighWater / 1024 / 1024);

   if (newSize == fHighWater)
      return maxCacheSize;

   else if (newSize < fHighWater) {
      ULong_t inUse = (fCache->GetSize() + fFree->GetSize()) * fPageSize;
      if (inUse > newSize) {
         // first free active cache to not contain more than newSize,
         // then delete free pages up to desired new limit
         if (ULong_t(fCache->GetSize() * fPageSize) > newSize) {
            if (Free(newSize) < 0) {
               Error("Resize", "error freeing pages");
               return -1;
            }
            fFree->Delete();
         } else {
            while (inUse > newSize) {
               TPage *p = (TPage*) fFree->First();
               if (!p) break;
               fFree->Remove(p);
               delete p;
               inUse -= fPageSize;
            }
         }
      }
   }
   fHighWater = newSize;
   fLowWater  = fHighWater * fLowLevel / 100;
   return oldSize;
}

//______________________________________________________________________________
Int_t TCache::GetActiveCacheSize() const
{
   // Get size of all allocated cache pages (in use and free pages).

   return Int_t(((fCache->GetSize()+fFree->GetSize())*fPageSize)/1024/1024);
}

//______________________________________________________________________________
void TCache::SetLowLevel(Int_t percentOfHigh)
{
   // Set the low water level. This is in percent of the maxCacheSize.
   // When the cache is full it will be freed up to percentOfHigh. The
   // default is kDfltLowLevel=70%.

   fLowLevel = percentOfHigh;
   fLowWater = fHighWater * fLowLevel / 100;
}
<|endoftext|>


<commit_before>// Copyright (2015) Gustav

#include "ride/builtinthemes.h"

#include <string>

typedef google::protobuf::RepeatedPtrField<ride::Theme> ThemeList;

ride::Theme* GetOrCreateTheme(ThemeList* themes, const std::string& name) {
  for (ride::Theme& t : *themes) {
    if (t.name() == name) return &t;
  }

  ride::Theme* temp = themes->Add();
  temp->set_name(name);
  temp->set_can_remove(false);
  return temp;
}

ride::Color MakeColor(google::protobuf::int32 r, google::protobuf::int32 g,
                      google::protobuf::int32 b) {
  ride::Color c;

  c.set_r(r);
  c.set_g(g);
  c.set_b(b);

  return c;
}

ride::Color MakeColor(google::protobuf::int32 c) { return MakeColor(c, c, c); }

ride::Color* NewColor(google::protobuf::int32 r, google::protobuf::int32 g,
                      google::protobuf::int32 b) {
  return new ride::Color(MakeColor(r, g, b));
}

ride::Color* NewColor(google::protobuf::int32 c) { return NewColor(c, c, c); }

ride::Style* NewStyle(ride::Color* front, ride::Color* back = NULL,
                      bool bold = false) {
  ride::Style* style = new ride::Style();

  if (front) {
    style->set_use_foreground(true);
    style->set_allocated_foreground(front);
  }

  if (back) {
    style->set_use_background(true);
    style->set_allocated_background(back);
  }

  if (bold) {
    style->set_use_bold(true);
    style->set_bold(true);
  }

  return style;
}

template <typename T>
T* New(const T& t) {
  return new T(t);
}

ride::Indicator MakeIndicator(const ride::Color& c) {
  ride::Indicator ind;
  ind.set_allocated_foreground(New(c));
  return ind;
}

//////////////////////////////////////////////////////////////////////////

void SetupDefaultTemplate(ride::FontsAndColors* colors) {
  colors->set_use_selection_background(true);
  colors->set_use_selection_foreground(true);
  colors->set_allocated_selection_foreground(NewColor(255, 255, 255));
  colors->set_allocated_selection_background(NewColor(0, 0, 0));

  ride::Color bkg = MakeColor(224);

  colors->set_allocated_default_style(
      NewStyle(NewColor(0), new ride::Color(bkg)));
  colors->set_allocated_line_number_style(NewStyle(0, new ride::Color(bkg)));
  colors->set_allocated_fold_margin_hi(NewColor(192));
  colors->set_allocated_fold_margin_low(NewColor(224));

  colors->set_allocated_selected_line(NewColor(255, 255, 0));  // yellow

  ride::Color comment = MakeColor(128, 64, 0);
  colors->set_allocated_style_comment(NewStyle(new ride::Color(comment)));
  colors->set_allocated_style_commentline(NewStyle(new ride::Color(comment)));
  colors->set_allocated_style_commentdoc(NewStyle(new ride::Color(comment)));
  colors->set_allocated_style_commentlinedoc(
      NewStyle(new ride::Color(comment)));
  colors->set_allocated_style_keyword(
      NewStyle(NewColor(0, 0, 255), NULL, true));

  colors->set_allocated_folderend_background(new ride::Color(bkg));
  colors->set_allocated_folderopenmid_background(new ride::Color(bkg));
  colors->set_allocated_foldermidtail_background(new ride::Color(bkg));
  colors->set_allocated_foldertail_background(new ride::Color(bkg));
  colors->set_allocated_foldersub_background(new ride::Color(bkg));
  colors->set_allocated_folder_background(new ride::Color(bkg));
  colors->set_allocated_folderopen_background(new ride::Color(bkg));

  colors->set_allocated_props_key(NewStyle(NewColor(128, 128, 255)));
  colors->set_allocated_props_section(NewStyle(NULL, NULL, true));

  colors->set_allocated_indicator_error(
      New(MakeIndicator(MakeColor(255, 60, 60))));
  colors->set_allocated_indicator_warning(
      New(MakeIndicator(MakeColor(0, 255, 0))));
  colors->set_allocated_indicator_search_highlight(
      New(MakeIndicator(MakeColor(200))));
  colors->set_allocated_indicator_select_highlight(
      New(MakeIndicator(MakeColor(180))));
}

//////////////////////////////////////////////////////////////////////////

// solarized colors from http://ethanschoonover.com/solarized
const ride::Color solarized_base03 = MakeColor(0, 43, 54);
const ride::Color solarized_base02 = MakeColor(7, 54, 66);
const ride::Color solarized_base01 = MakeColor(88, 110, 117);
const ride::Color solarized_base00 = MakeColor(101, 123, 131);
const ride::Color solarized_base0 = MakeColor(131, 148, 150);
const ride::Color solarized_base1 = MakeColor(147, 161, 161);
const ride::Color solarized_base2 = MakeColor(238, 232, 213);
const ride::Color solarized_base3 = MakeColor(253, 246, 227);
const ride::Color solarized_yellow = MakeColor(181, 137, 0);
const ride::Color solarized_orange = MakeColor(203, 75, 22);
const ride::Color solarized_red = MakeColor(220, 50, 47);
const ride::Color solarized_magenta = MakeColor(211, 54, 130);
const ride::Color solarized_violet = MakeColor(108, 113, 196);
const ride::Color solarized_blue = MakeColor(38, 139, 210);
const ride::Color solarized_cyan = MakeColor(42, 161, 152);
const ride::Color solarized_green = MakeColor(133, 153, 0);

//////////////////////////////////////////////////////////////////////////

void AddBuiltInThemes(::ride::Settings* settings) {
  ThemeList* themes = settings->mutable_themes();

  ride::Theme* default_theme = GetOrCreateTheme(themes, "Ride (default)");
  SetupDefaultTemplate(default_theme->mutable_data());

  if (false == settings->has_fonts_and_colors()) {
    // if the current settings is missing the fonts and colors
    // apply the default theme
    settings->set_allocated_fonts_and_colors(
        new ride::FontsAndColors(default_theme->data()));
  }
}
<commit_msg>renamed stuff in theme code for #64<commit_after>// Copyright (2015) Gustav

#include "ride/builtinthemes.h"

#include <string>

typedef google::protobuf::RepeatedPtrField<ride::Theme> ThemeList;

ride::Theme* GetOrCreateTheme(ThemeList* themes, const std::string& name) {
  for (ride::Theme& t : *themes) {
    if (t.name() == name) return &t;
  }

  ride::Theme* temp = themes->Add();
  temp->set_name(name);
  temp->set_can_remove(false);
  return temp;
}

ride::Color Color(google::protobuf::int32 r, google::protobuf::int32 g,
                  google::protobuf::int32 b) {
  ride::Color c;

  c.set_r(r);
  c.set_g(g);
  c.set_b(b);

  return c;
}

ride::Color Color(google::protobuf::int32 c) { return Color(c, c, c); }

ride::Style Style(ride::Color* front, ride::Color* back = NULL,
                  bool bold = false) {
  ride::Style style;

  if (front) {
    style.set_use_foreground(true);
    style.set_allocated_foreground(front);
  }

  if (back) {
    style.set_use_background(true);
    style.set_allocated_background(back);
  }

  if (bold) {
    style.set_use_bold(true);
    style.set_bold(true);
  }

  return style;
}

template <typename T>
T* New(const T& t) {
  return new T(t);
}

ride::Indicator Indicator(const ride::Color& c) {
  ride::Indicator ind;
  ind.set_allocated_foreground(New(c));
  return ind;
}

//////////////////////////////////////////////////////////////////////////

void SetupDefaultTemplate(ride::FontsAndColors* colors) {
  colors->set_use_selection_background(true);
  colors->set_use_selection_foreground(true);
  colors->set_allocated_selection_foreground(New(Color(255, 255, 255)));
  colors->set_allocated_selection_background(New(Color(0, 0, 0)));

  ride::Color bkg = Color(224);

  colors->set_allocated_default_style(New(Style(New(Color(0)), New(bkg))));
  colors->set_allocated_line_number_style(New(Style(NULL, New(bkg))));
  colors->set_allocated_fold_margin_hi(New(Color(192)));
  colors->set_allocated_fold_margin_low(New(Color(224)));

  colors->set_allocated_selected_line(New(Color(255, 255, 0)));  // yellow

  ride::Color comment = Color(128, 64, 0);
  colors->set_allocated_style_comment(New(Style(New(comment))));
  colors->set_allocated_style_commentline(New(Style(New(comment))));
  colors->set_allocated_style_commentdoc(New(Style(New(comment))));
  colors->set_allocated_style_commentlinedoc(New(Style(New(comment))));
  colors->set_allocated_style_keyword(
      New(Style(New(Color(0, 0, 255)), NULL, true)));

  colors->set_allocated_folderend_background(New(bkg));
  colors->set_allocated_folderopenmid_background(New(bkg));
  colors->set_allocated_foldermidtail_background(New(bkg));
  colors->set_allocated_foldertail_background(New(bkg));
  colors->set_allocated_foldersub_background(New(bkg));
  colors->set_allocated_folder_background(New(bkg));
  colors->set_allocated_folderopen_background(New(bkg));

  colors->set_allocated_props_key(New(Style(New(Color(128, 128, 255)))));
  colors->set_allocated_props_section(New(Style(NULL, NULL, true)));

  colors->set_allocated_indicator_error(New(Indicator(Color(255, 60, 60))));
  colors->set_allocated_indicator_warning(New(Indicator(Color(0, 255, 0))));
  colors->set_allocated_indicator_search_highlight(New(Indicator(Color(200))));
  colors->set_allocated_indicator_select_highlight(New(Indicator(Color(180))));
}

//////////////////////////////////////////////////////////////////////////

// solarized colors from http://ethanschoonover.com/solarized
const ride::Color solarized_base03 = Color(0, 43, 54);
const ride::Color solarized_base02 = Color(7, 54, 66);
const ride::Color solarized_base01 = Color(88, 110, 117);
const ride::Color solarized_base00 = Color(101, 123, 131);
const ride::Color solarized_base0 = Color(131, 148, 150);
const ride::Color solarized_base1 = Color(147, 161, 161);
const ride::Color solarized_base2 = Color(238, 232, 213);
const ride::Color solarized_base3 = Color(253, 246, 227);
const ride::Color solarized_yellow = Color(181, 137, 0);
const ride::Color solarized_orange = Color(203, 75, 22);
const ride::Color solarized_red = Color(220, 50, 47);
const ride::Color solarized_magenta = Color(211, 54, 130);
const ride::Color solarized_violet = Color(108, 113, 196);
const ride::Color solarized_blue = Color(38, 139, 210);
const ride::Color solarized_cyan = Color(42, 161, 152);
const ride::Color solarized_green = Color(133, 153, 0);

//////////////////////////////////////////////////////////////////////////

void AddBuiltInThemes(::ride::Settings* settings) {
  ThemeList* themes = settings->mutable_themes();

  ride::Theme* default_theme = GetOrCreateTheme(themes, "Ride (default)");
  SetupDefaultTemplate(default_theme->mutable_data());

  if (false == settings->has_fonts_and_colors()) {
    // if the current settings is missing the fonts and colors
    // apply the default theme
    settings->set_allocated_fonts_and_colors(
        new ride::FontsAndColors(default_theme->data()));
  }
}
<|endoftext|>


<commit_before>//==============================================================================
// Single cell view information graphs widget
//==============================================================================

#include "cellmlfileruntime.h"
#include "propertyeditorwidget.h"
#include "singlecellviewinformationgraphswidget.h"

//==============================================================================

#include <QHeaderView>
#include <QLabel>
#include <QSettings>

//==============================================================================

namespace OpenCOR {
namespace SingleCellView {

//==============================================================================

SingleCellViewInformationGraphsWidget::SingleCellViewInformationGraphsWidget(QWidget *pParent) :
    QStackedWidget(pParent),
    mPropertyEditors(QMap<SingleCellViewGraphPanelWidget *, Core::PropertyEditorWidget *>()),
    mColumnWidths(QList<int>())
{
    // Create a widget that will be shown whenever there are no graphs
    // associated with the current plotting area

    mNoGraphsMessageWidget = new QLabel(pParent);

    mNoGraphsMessageWidget->setAlignment(Qt::AlignCenter);
    mNoGraphsMessageWidget->setAutoFillBackground(true);
    mNoGraphsMessageWidget->setBackgroundRole(QPalette::Base);
    mNoGraphsMessageWidget->setMargin(3);
    mNoGraphsMessageWidget->setWordWrap(true);

    addWidget(mNoGraphsMessageWidget);

    // Determine the default width of each column of our property editors

    Core::PropertyEditorWidget *tempPropertyEditor = new Core::PropertyEditorWidget(this);

    for (int i = 0, iMax = tempPropertyEditor->header()->count(); i < iMax; ++i)
        mColumnWidths.append(tempPropertyEditor->columnWidth(i));

    delete tempPropertyEditor;
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::retranslateUi()
{
    // Retranslate our no graphs message widget

    mNoGraphsMessageWidget->setText(tr("There are no graphs..."));

    // Retranslate all our property editors

    foreach (Core::PropertyEditorWidget *propertyEditor, mPropertyEditors)
        propertyEditor->retranslateUi();
}

//==============================================================================

static const QString SettingsColumnWidth = "ColumnWidth%1";

//==============================================================================

void SingleCellViewInformationGraphsWidget::loadSettings(QSettings *pSettings)
{
    // Retrieve the width of each column of our property editors

    for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
        mColumnWidths[i] = pSettings->value(SettingsColumnWidth.arg(i),
                                            mColumnWidths.at(i)).toInt();

}

//==============================================================================

void SingleCellViewInformationGraphsWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of the width of each column of our current property editor

    for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
        pSettings->setValue(SettingsColumnWidth.arg(i), mColumnWidths.at(i));
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::initialize(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Retrieve the property editor for the given file name or create one, if
    // none exists

    Core::PropertyEditorWidget *propertyEditor = mPropertyEditors.value(pGraphPanel);

    if (!propertyEditor) {
        // No property editor exists for the given graph panel, so create one

        propertyEditor = new Core::PropertyEditorWidget(this);

        // Initialise our property editor's columns' width

        for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
            propertyEditor->setColumnWidth(i, mColumnWidths.at(i));

        // Keep track of when the user changes a property value

        connect(propertyEditor, SIGNAL(propertyChanged(Core::Property *)),
                this, SLOT(propertyChanged(Core::Property *)));

        // Add our new property editor to ourselves

        addWidget(propertyEditor);

        // Keep track of our new property editor

        mPropertyEditors.insert(pGraphPanel, propertyEditor);
    }

    // Set our retrieved property editor as our current widget, but only if it
    // isn't empty

    if (propertyEditor->properties().count())
        setCurrentWidget(propertyEditor);
    else
        setCurrentWidget(mNoGraphsMessageWidget);
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::finalize(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Remove any track of our property editor

    mPropertyEditors.remove(pGraphPanel);
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::finishPropertyEditing()
{
    // Retrieve our current property editor, if any

    Core::PropertyEditorWidget *propertyEditor = qobject_cast<Core::PropertyEditorWidget *>(currentWidget());

    if (!propertyEditor)
        return;

    // Finish the editing of our current property editor

    propertyEditor->finishPropertyEditing();
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::requireGraph(CellMLSupport::CellmlFileRuntimeParameter *pParameterX,
                                                         CellMLSupport::CellmlFileRuntimeParameter *pParameterY)
{
//---GRY--- TO BE DONE...
    // Keep track of the graph requirement

qDebug(">>> Graph required for:");
qDebug(">>>  - X: %s", qPrintable(pParameterX->name()));
qDebug(">>>  - Y: %s", qPrintable(pParameterY->name()));
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::propertyChanged(Core::Property *pProperty)
{
//---GRY--- TO BE DONE...

Q_UNUSED(pProperty);
}

//==============================================================================

}   // namespace SingleCellView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<commit_msg>Some minor cleaning up.<commit_after>//==============================================================================
// Single cell view information graphs widget
//==============================================================================

#include "cellmlfileruntime.h"
#include "propertyeditorwidget.h"
#include "singlecellviewinformationgraphswidget.h"

//==============================================================================

#include <QHeaderView>
#include <QLabel>
#include <QSettings>

//==============================================================================

namespace OpenCOR {
namespace SingleCellView {

//==============================================================================

SingleCellViewInformationGraphsWidget::SingleCellViewInformationGraphsWidget(QWidget *pParent) :
    QStackedWidget(pParent),
    mPropertyEditors(QMap<SingleCellViewGraphPanelWidget *, Core::PropertyEditorWidget *>()),
    mColumnWidths(QList<int>())
{
    // Create a widget that will be shown whenever there are no graphs
    // associated with the current plotting area

    mNoGraphsMessageWidget = new QLabel(pParent);

    mNoGraphsMessageWidget->setAlignment(Qt::AlignCenter);
    mNoGraphsMessageWidget->setAutoFillBackground(true);
    mNoGraphsMessageWidget->setBackgroundRole(QPalette::Base);
    mNoGraphsMessageWidget->setWordWrap(true);

    addWidget(mNoGraphsMessageWidget);

    // Determine the default width of each column of our property editors

    Core::PropertyEditorWidget *tempPropertyEditor = new Core::PropertyEditorWidget(this);

    for (int i = 0, iMax = tempPropertyEditor->header()->count(); i < iMax; ++i)
        mColumnWidths.append(tempPropertyEditor->columnWidth(i));

    delete tempPropertyEditor;
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::retranslateUi()
{
    // Retranslate our no graphs message widget

    mNoGraphsMessageWidget->setText(tr("There are no graphs..."));

    // Retranslate all our property editors

    foreach (Core::PropertyEditorWidget *propertyEditor, mPropertyEditors)
        propertyEditor->retranslateUi();
}

//==============================================================================

static const QString SettingsColumnWidth = "ColumnWidth%1";

//==============================================================================

void SingleCellViewInformationGraphsWidget::loadSettings(QSettings *pSettings)
{
    // Retrieve the width of each column of our property editors

    for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
        mColumnWidths[i] = pSettings->value(SettingsColumnWidth.arg(i),
                                            mColumnWidths.at(i)).toInt();

}

//==============================================================================

void SingleCellViewInformationGraphsWidget::saveSettings(QSettings *pSettings) const
{
    // Keep track of the width of each column of our current property editor

    for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
        pSettings->setValue(SettingsColumnWidth.arg(i), mColumnWidths.at(i));
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::initialize(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Retrieve the property editor for the given file name or create one, if
    // none exists

    Core::PropertyEditorWidget *propertyEditor = mPropertyEditors.value(pGraphPanel);

    if (!propertyEditor) {
        // No property editor exists for the given graph panel, so create one

        propertyEditor = new Core::PropertyEditorWidget(this);

        // Initialise our property editor's columns' width

        for (int i = 0, iMax = mColumnWidths.size(); i < iMax; ++i)
            propertyEditor->setColumnWidth(i, mColumnWidths.at(i));

        // Keep track of when the user changes a property value

        connect(propertyEditor, SIGNAL(propertyChanged(Core::Property *)),
                this, SLOT(propertyChanged(Core::Property *)));

        // Add our new property editor to ourselves

        addWidget(propertyEditor);

        // Keep track of our new property editor

        mPropertyEditors.insert(pGraphPanel, propertyEditor);
    }

    // Set our retrieved property editor as our current widget, but only if it
    // isn't empty

    if (propertyEditor->properties().count())
        setCurrentWidget(propertyEditor);
    else
        setCurrentWidget(mNoGraphsMessageWidget);
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::finalize(SingleCellViewGraphPanelWidget *pGraphPanel)
{
    // Remove any track of our property editor

    mPropertyEditors.remove(pGraphPanel);
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::finishPropertyEditing()
{
    // Retrieve our current property editor, if any

    Core::PropertyEditorWidget *propertyEditor = qobject_cast<Core::PropertyEditorWidget *>(currentWidget());

    if (!propertyEditor)
        return;

    // Finish the editing of our current property editor

    propertyEditor->finishPropertyEditing();
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::requireGraph(CellMLSupport::CellmlFileRuntimeParameter *pParameterX,
                                                         CellMLSupport::CellmlFileRuntimeParameter *pParameterY)
{
//---GRY--- TO BE DONE...
    // Keep track of the graph requirement

qDebug(">>> Graph required for:");
qDebug(">>>  - X: %s", qPrintable(pParameterX->name()));
qDebug(">>>  - Y: %s", qPrintable(pParameterY->name()));
}

//==============================================================================

void SingleCellViewInformationGraphsWidget::propertyChanged(Core::Property *pProperty)
{
//---GRY--- TO BE DONE...

Q_UNUSED(pProperty);
}

//==============================================================================

}   // namespace SingleCellView
}   // namespace OpenCOR

//==============================================================================
// End of file
//==============================================================================
<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AndroidApplication.h"

#include <Corrade/Utility/AndroidStreamBuffer.h>
#include <Corrade/Utility/Debug.h>

#include "Magnum/Context.h"

#include "Implementation/Egl.h"

namespace Magnum { namespace Platform {

#ifndef DOXYGEN_GENERATING_OUTPUT
AndroidApplication::AndroidApplication(const Arguments& arguments): AndroidApplication{arguments, Configuration{}} {}
#endif

AndroidApplication::AndroidApplication(const Arguments& arguments, const Configuration& configuration): AndroidApplication{arguments, nullptr} {
    createContext(configuration);
}

AndroidApplication::AndroidApplication(const Arguments& arguments, std::nullptr_t): _state(arguments) {
    /* Redirect debug output to Android log */
    _logOutput.reset(new LogOutput);
}

AndroidApplication::~AndroidApplication() {
    eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(_display, _context);
    eglDestroySurface(_display, _surface);
    eglTerminate(_display);
}

struct AndroidApplication::LogOutput {
    LogOutput();

    Utility::AndroidLogStreamBuffer debugBuffer, warningBuffer, errorBuffer;
    std::ostream debugStream, warningStream, errorStream;
};

AndroidApplication::LogOutput::LogOutput():
    debugBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Info, "magnum"),
    warningBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Warning, "magnum"),
    errorBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Error, "magnum"),
    debugStream(&debugBuffer), warningStream(&warningBuffer), errorStream(&errorBuffer)
{
    Debug::setOutput(&debugStream);
    Warning::setOutput(&warningStream);
    Error::setOutput(&errorStream);
}

void AndroidApplication::createContext() { createContext({}); }

void AndroidApplication::createContext(const Configuration& configuration) {
    if(!tryCreateContext(configuration)) std::exit(32);
}

bool AndroidApplication::tryCreateContext(const Configuration& configuration) {
    /* Initialize EGL */
    _display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if(!eglInitialize(_display, nullptr, nullptr)) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot initialize EGL:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Choose config */
    const EGLint configAttributes[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_NONE
    };
    EGLint configCount;
    EGLConfig config;
    if(!eglChooseConfig(_display, configAttributes, &config, 1, &configCount)) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot choose EGL config:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Resize native window and match it to the selected format */
    EGLint format;
    CORRADE_INTERNAL_ASSERT_OUTPUT(eglGetConfigAttrib(_display, config, EGL_NATIVE_VISUAL_ID, &format));
    ANativeWindow_setBuffersGeometry(_state->window,
        configuration.size().isZero() ? 0 : configuration.size().x(),
        configuration.size().isZero() ? 0 : configuration.size().y(), format);

    /* Create surface and context */
    if(!(_surface = eglCreateWindowSurface(_display, config, _state->window, nullptr))) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL window surface:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }
    const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES2
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #elif defined(MAGNUM_TARGET_GLES3)
        EGL_CONTEXT_CLIENT_VERSION, 3,
        #else
        #error Android with desktop OpenGL? Wow, that is a new thing.
        #endif
        EGL_NONE
    };
    if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, contextAttributes))) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL context:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Make the context current */
    CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _context));

    _c.reset(new Context);
    return true;
}

void AndroidApplication::swapBuffers() {
    eglSwapBuffers(_display, _surface);
}

void AndroidApplication::viewportEvent(const Vector2i&) {}
void AndroidApplication::mousePressEvent(MouseEvent&) {}
void AndroidApplication::mouseReleaseEvent(MouseEvent&) {}
void AndroidApplication::mouseMoveEvent(MouseMoveEvent&) {}

namespace {
    struct Data {
        Data(std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&)): instancer(instancer) {}

        std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&);
        std::unique_ptr<AndroidApplication> instance;
    };
}

void AndroidApplication::commandEvent(android_app* state, int32_t cmd) {
    Data& data = *static_cast<Data*>(state->userData);

    switch (cmd) {
        case APP_CMD_SAVE_STATE:
            /** @todo Make use of this */
            break;

        case APP_CMD_INIT_WINDOW:
            /* Create the application */
            if(!data.instance) {
                data.instance = data.instancer(state);
                data.instance->drawEvent();
            }
            break;

        case APP_CMD_TERM_WINDOW:
            /* Destroy the application */
            data.instance.reset();
            break;

        case APP_CMD_GAINED_FOCUS:
        case APP_CMD_LOST_FOCUS:
            /** @todo Make use of these */
            break;
    }
}

std::int32_t AndroidApplication::inputEvent(android_app* state, AInputEvent* event) {
    CORRADE_INTERNAL_ASSERT(static_cast<Data*>(state->userData)->instance);
    AndroidApplication& app = *static_cast<Data*>(state->userData)->instance;
    if(AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        const std::int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
        switch(action) {
            case AMOTION_EVENT_ACTION_DOWN:
            case AMOTION_EVENT_ACTION_UP: {
                MouseEvent e(event);
                action == AMOTION_EVENT_ACTION_DOWN ? app.mousePressEvent(e) : app.mouseReleaseEvent(e);
                return e.isAccepted() ? 1 : 0;
            }

            case AMOTION_EVENT_ACTION_MOVE: {
                MouseMoveEvent e(event);
                app.mouseMoveEvent(e);
                return e.isAccepted() ? 1 : 0;
            }
        }

    /** @todo Implement also other input events */
    }

    return 0;
}

void AndroidApplication::exec(android_app* state, std::unique_ptr<AndroidApplication>(*instancer)(const Arguments&)) {
    state->onAppCmd = commandEvent;
    state->onInputEvent = inputEvent;

    /* Make sure the glue isn't stripped. WHY WHYYY CAN'T THIS BE DONE SOME
       SANE WAY WHYY */
    app_dummy();

    /** @todo Make use of saved state */
    Data data{instancer};
    state->userData = &data;

    for(;;) {
        /* Read all pending events. Block and wait for them only if the app
           doesn't want to redraw immediately WHY THIS GODDAMN THING DOESNT
           HAVE SOMETHING LIKE WAIT FOR EVENT SO I NEED TO TANGLE THIS TANGLED
           MESS OF HELL */
        int ident, events;
        android_poll_source* source;
        while((ident = ALooper_pollAll(
            data.instance && (data.instance->_flags & Flag::Redraw) ? 0 : -1,
            nullptr, &events, reinterpret_cast<void**>(&source))) >= 0)
        {
            /* Process this event OH SIR MAY MY POOR EXISTENCE CALL THIS
               FUNCTION FOR YOU IF YOU DON'T MIND? */
            if(source) source->process(state, source);

            /* Exit WHY THIS HAS TO BE HANDLED HERE WHILE EVERY OTHER THING
               IS HANDLED THROUGH CALLBACK GODDAMMIT */
            if(state->destroyRequested != 0) return;
        }

        /* Redraw the app if it wants to be redrawn. Frame limiting is done by
           Android itself */
        if(data.instance && (data.instance->_flags & Flag::Redraw))
            data.instance->drawEvent();
    }

    state->userData = nullptr;
}

}}
<commit_msg>Platform: fix AndroidApplication compilation.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013, 2014
              Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "AndroidApplication.h"

#include <Corrade/Utility/AndroidStreamBuffer.h>
#include <Corrade/Utility/Debug.h>

#include "Magnum/Context.h"

#include "Implementation/Egl.h"

namespace Magnum { namespace Platform {

AndroidApplication::~AndroidApplication() {
    eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglDestroyContext(_display, _context);
    eglDestroySurface(_display, _surface);
    eglTerminate(_display);
}

struct AndroidApplication::LogOutput {
    LogOutput();

    Utility::AndroidLogStreamBuffer debugBuffer, warningBuffer, errorBuffer;
    std::ostream debugStream, warningStream, errorStream;
};

#ifndef DOXYGEN_GENERATING_OUTPUT
AndroidApplication::AndroidApplication(const Arguments& arguments): AndroidApplication{arguments, Configuration{}} {}
#endif

AndroidApplication::AndroidApplication(const Arguments& arguments, const Configuration& configuration): AndroidApplication{arguments, nullptr} {
    createContext(configuration);
}

AndroidApplication::AndroidApplication(const Arguments& arguments, std::nullptr_t): _state(arguments) {
    /* Redirect debug output to Android log */
    _logOutput.reset(new LogOutput);
}

AndroidApplication::LogOutput::LogOutput():
    debugBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Info, "magnum"),
    warningBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Warning, "magnum"),
    errorBuffer(Utility::AndroidLogStreamBuffer::LogPriority::Error, "magnum"),
    debugStream(&debugBuffer), warningStream(&warningBuffer), errorStream(&errorBuffer)
{
    Debug::setOutput(&debugStream);
    Warning::setOutput(&warningStream);
    Error::setOutput(&errorStream);
}

void AndroidApplication::createContext() { createContext({}); }

void AndroidApplication::createContext(const Configuration& configuration) {
    if(!tryCreateContext(configuration)) std::exit(32);
}

bool AndroidApplication::tryCreateContext(const Configuration& configuration) {
    /* Initialize EGL */
    _display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if(!eglInitialize(_display, nullptr, nullptr)) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot initialize EGL:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Choose config */
    const EGLint configAttributes[] = {
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_BLUE_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_RED_SIZE, 8,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
        EGL_NONE
    };
    EGLint configCount;
    EGLConfig config;
    if(!eglChooseConfig(_display, configAttributes, &config, 1, &configCount)) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot choose EGL config:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Resize native window and match it to the selected format */
    EGLint format;
    CORRADE_INTERNAL_ASSERT_OUTPUT(eglGetConfigAttrib(_display, config, EGL_NATIVE_VISUAL_ID, &format));
    ANativeWindow_setBuffersGeometry(_state->window,
        configuration.size().isZero() ? 0 : configuration.size().x(),
        configuration.size().isZero() ? 0 : configuration.size().y(), format);

    /* Create surface and context */
    if(!(_surface = eglCreateWindowSurface(_display, config, _state->window, nullptr))) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL window surface:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }
    const EGLint contextAttributes[] = {
        #ifdef MAGNUM_TARGET_GLES2
        EGL_CONTEXT_CLIENT_VERSION, 2,
        #elif defined(MAGNUM_TARGET_GLES3)
        EGL_CONTEXT_CLIENT_VERSION, 3,
        #else
        #error Android with desktop OpenGL? Wow, that is a new thing.
        #endif
        EGL_NONE
    };
    if(!(_context = eglCreateContext(_display, config, EGL_NO_CONTEXT, contextAttributes))) {
        Error() << "Platform::AndroidApplication::tryCreateContext(): cannot create EGL context:"
                << Implementation::eglErrorString(eglGetError());
        return false;
    }

    /* Make the context current */
    CORRADE_INTERNAL_ASSERT_OUTPUT(eglMakeCurrent(_display, _surface, _surface, _context));

    _c.reset(new Context);
    return true;
}

void AndroidApplication::swapBuffers() {
    eglSwapBuffers(_display, _surface);
}

void AndroidApplication::viewportEvent(const Vector2i&) {}
void AndroidApplication::mousePressEvent(MouseEvent&) {}
void AndroidApplication::mouseReleaseEvent(MouseEvent&) {}
void AndroidApplication::mouseMoveEvent(MouseMoveEvent&) {}

namespace {
    struct Data {
        Data(std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&)): instancer(instancer) {}

        std::unique_ptr<AndroidApplication>(*instancer)(const AndroidApplication::Arguments&);
        std::unique_ptr<AndroidApplication> instance;
    };
}

void AndroidApplication::commandEvent(android_app* state, int32_t cmd) {
    Data& data = *static_cast<Data*>(state->userData);

    switch (cmd) {
        case APP_CMD_SAVE_STATE:
            /** @todo Make use of this */
            break;

        case APP_CMD_INIT_WINDOW:
            /* Create the application */
            if(!data.instance) {
                data.instance = data.instancer(state);
                data.instance->drawEvent();
            }
            break;

        case APP_CMD_TERM_WINDOW:
            /* Destroy the application */
            data.instance.reset();
            break;

        case APP_CMD_GAINED_FOCUS:
        case APP_CMD_LOST_FOCUS:
            /** @todo Make use of these */
            break;
    }
}

std::int32_t AndroidApplication::inputEvent(android_app* state, AInputEvent* event) {
    CORRADE_INTERNAL_ASSERT(static_cast<Data*>(state->userData)->instance);
    AndroidApplication& app = *static_cast<Data*>(state->userData)->instance;
    if(AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
        const std::int32_t action = AMotionEvent_getAction(event) & AMOTION_EVENT_ACTION_MASK;
        switch(action) {
            case AMOTION_EVENT_ACTION_DOWN:
            case AMOTION_EVENT_ACTION_UP: {
                MouseEvent e(event);
                action == AMOTION_EVENT_ACTION_DOWN ? app.mousePressEvent(e) : app.mouseReleaseEvent(e);
                return e.isAccepted() ? 1 : 0;
            }

            case AMOTION_EVENT_ACTION_MOVE: {
                MouseMoveEvent e(event);
                app.mouseMoveEvent(e);
                return e.isAccepted() ? 1 : 0;
            }
        }

    /** @todo Implement also other input events */
    }

    return 0;
}

void AndroidApplication::exec(android_app* state, std::unique_ptr<AndroidApplication>(*instancer)(const Arguments&)) {
    state->onAppCmd = commandEvent;
    state->onInputEvent = inputEvent;

    /* Make sure the glue isn't stripped. WHY WHYYY CAN'T THIS BE DONE SOME
       SANE WAY WHYY */
    app_dummy();

    /** @todo Make use of saved state */
    Data data{instancer};
    state->userData = &data;

    for(;;) {
        /* Read all pending events. Block and wait for them only if the app
           doesn't want to redraw immediately WHY THIS GODDAMN THING DOESNT
           HAVE SOMETHING LIKE WAIT FOR EVENT SO I NEED TO TANGLE THIS TANGLED
           MESS OF HELL */
        int ident, events;
        android_poll_source* source;
        while((ident = ALooper_pollAll(
            data.instance && (data.instance->_flags & Flag::Redraw) ? 0 : -1,
            nullptr, &events, reinterpret_cast<void**>(&source))) >= 0)
        {
            /* Process this event OH SIR MAY MY POOR EXISTENCE CALL THIS
               FUNCTION FOR YOU IF YOU DON'T MIND? */
            if(source) source->process(state, source);

            /* Exit WHY THIS HAS TO BE HANDLED HERE WHILE EVERY OTHER THING
               IS HANDLED THROUGH CALLBACK GODDAMMIT */
            if(state->destroyRequested != 0) return;
        }

        /* Redraw the app if it wants to be redrawn. Frame limiting is done by
           Android itself */
        if(data.instance && (data.instance->_flags & Flag::Redraw))
            data.instance->drawEvent();
    }

    state->userData = nullptr;
}

}}
<|endoftext|>