<commit_before>/*
 * TwoWire.h - TWI/I2C library for Linux Userspace
 * Copyright (c) 2013 Parav https://github.com/meanbot.
 * All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
#include <string.h>
#include "../wiring/wiring.h"
}

#include "Wire.h"

// #include <trace.h>
#define MY_TRACE_PREFIX "Wire"

TwoWire::TwoWire(void(*_beginCb)(void)) : rxBufferIndex(0), rxBufferLength(0),
					  txAddress(0), txBufferLength(0),
					  srvBufferIndex(0), srvBufferLength(0),
					  onBeginCallback(_beginCb),
					  adapter_nr(-1), i2c_fd(-1),
					  i2c_transfer(0)
{
	// Empty
}

void TwoWire::begin(void)
{
	// muxSelectI2c(0);
	if (onBeginCallback)
		onBeginCallback();
	// if ((adapter_nr = i2c_getadapter(I2C2)) < 0) {
	// 	return;
	// }
	if (BOARD == GALILEO)
	{
		adapter_nr = 0;
	}
	else
	if (BOARD == EDISON)
	{
		adapter_nr = 6;
	}
	if ((i2c_fd = i2c_openadapter(adapter_nr)) < 0) {
		return;
	}

}

void TwoWire::begin(uint8_t address)
{
	if (onBeginCallback)
		onBeginCallback();
}

void TwoWire::begin(int address)
{
	begin((uint8_t) address);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
	if (quantity > BUFFER_LENGTH)
		quantity = BUFFER_LENGTH;

	/* Set slave address via ioctl  */
	i2c_setslave(i2c_fd, address);

	// if(i2c_transfer) {
	// /* Need to perform a combined read/write operation
	//  */
	// 	i2c_transfer = 0;
	// 	if (sendStop == false)
	// 		return 0;
	// 	i2c_add_to_buf(address, 1, rxBuffer, quantity);
	// 	if (!i2c_readwrite(i2c_fd)) {
	// 		rxBufferIndex = 0;
	// 		rxBufferLength = quantity;
	// 		i2c_transfer = 0;
	// 		return quantity;
	// 	} else
	// 		return 0;
	// }
	if (i2c_readbytes(i2c_fd, rxBuffer, quantity) < 0)
		return 0;
	// set rx buffer iterator vars
	rxBufferIndex = 0;
	rxBufferLength = quantity;

	return quantity;
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
}

uint8_t TwoWire::requestFrom(int address, int quantity)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
}

uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop);
}

void TwoWire::beginTransmission(uint8_t address)
{
	if (i2c_fd < 0 || adapter_nr < 0)
		return;
	/* set slave address via ioctl in case we need to perform terminating
	 * write operation
	 */
	i2c_setslave(i2c_fd, address);
	// save address of target and empty buffer
	txAddress = address;
	txBufferLength = 0;
}

void TwoWire::beginTransmission(int address)
{
	beginTransmission((uint8_t) address);
}

//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
	int err;
	if (sendStop == true) {

		// transmit buffer (blocking)
		if (txBufferLength > 1)
			err = i2c_writebytes(i2c_fd, txBuffer, txBufferLength);
		else if (txBufferLength == 1)
			err = i2c_writebyte(i2c_fd, *txBuffer);
		else
		/* FIXME: A zero byte transmit is typically used to check for an
		 * ACK from the slave device. I'm not sure if this is the
		 * correct way to do this.
		 */
			err = i2c_readbyte(i2c_fd);
		// empty buffer
		txBufferLength = 0;
		if (err < 0)
			return 2;
		return 0;
	} else {
	/* sendStop = false
	 * pretend we have held the bus while
	 * actually waiting for the next operation
	 */
		// i2c_add_to_buf(txAddress, 0, txBuffer, txBufferLength);
		// i2c_transfer = 1;
		return 0;
	}
}

//	This provides backwards compatibility with the original
//	definition, and expected behaviour, of endTransmission
//
uint8_t TwoWire::endTransmission(void)
{
	return endTransmission(true);
}

size_t TwoWire::write(uint8_t data)
{
	if (txBufferLength >= BUFFER_LENGTH)
		return 0;
	txBuffer[txBufferLength++] = data;
	return 1;
}

size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
	for (size_t i = 0; i < quantity; ++i) {
		if (txBufferLength >= BUFFER_LENGTH)
			return i;
		txBuffer[txBufferLength++] = data[i];
	}
	return quantity;
}

int TwoWire::available(void)
{
	return rxBufferLength - rxBufferIndex;
}

int TwoWire::read(void)
{
	if (rxBufferIndex < rxBufferLength)
		return rxBuffer[rxBufferIndex++];
	return -1;
}

int TwoWire::peek(void)
{
	if (rxBufferIndex < rxBufferLength)
		return rxBuffer[rxBufferIndex];
	return -1;
}

void TwoWire::flush(void)
{
	// Do nothing, use endTransmission(..) to force
	// data transfer.
}

void TwoWire::onReceive(void(*function)(int))
{
	onReceiveCallback = function;
}

void TwoWire::onRequest(void(*function)(void)) {
	onRequestCallback = function;
}

void TwoWire::onService(void)
{
}

//#if WIRE_INTERFACES_COUNT > 0
static void Wire_Init(void)
{
}

TwoWire Wire = TwoWire(Wire_Init);

void WIRE_ISR_HANDLER(void) {
	Wire.onService();
}
//#endif

#if WIRE_INTERFACES_COUNT > 1
static void Wire1_Init(void)
{
	if ((adapter_nr = i2c_getadapter(I2C1)) < 0) {
		return;
	}
	if ((i2c_fd = i2c_openadapter) < 0) {
		return;
	}
}

TwoWire Wire1 = TwoWire(Wire1_Init);

void WIRE1_ISR_HANDLER(void) {
	Wire1.onService();
}
#endif
<commit_msg>Update Wire.cpp<commit_after>/*
 * TwoWire.h - TWI/I2C library for Linux Userspace
 * Copyright (c) 2013 Parav https://github.com/meanbot.
 * All rights reserved.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

extern "C" {
#include <string.h>
#include "../wiring/wiring.h"
}

#include "Wire.h"

// #include <trace.h>
#define MY_TRACE_PREFIX "Wire"

TwoWire::TwoWire(void(*_beginCb)(void)) : rxBufferIndex(0), rxBufferLength(0),
					  txAddress(0), txBufferLength(0),
					  srvBufferIndex(0), srvBufferLength(0),
					  onBeginCallback(_beginCb),
					  adapter_nr(-1), i2c_fd(-1),
					  i2c_transfer(0)
{
	// Empty
}

void TwoWire::begin(void)
{
	// muxSelectI2c(0);
	if (onBeginCallback)
		onBeginCallback();
	// if ((adapter_nr = i2c_getadapter(I2C2)) < 0) {
	// 	return;
	// }
	if (BOARd == RUN_RASPBERRYPI || BOARD == RUN_GALILEO)
	{
		adapter_nr = 0;
	}
	else
	if (BOARD == RUN_EDISON)
	{
		adapter_nr = 6;
	}
	if ((i2c_fd = i2c_openadapter(adapter_nr)) < 0) {
		return;
	}

}

void TwoWire::begin(uint8_t address)
{
	if (onBeginCallback)
		onBeginCallback();
}

void TwoWire::begin(int address)
{
	begin((uint8_t) address);
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity, uint8_t sendStop)
{
	if (quantity > BUFFER_LENGTH)
		quantity = BUFFER_LENGTH;

	/* Set slave address via ioctl  */
	i2c_setslave(i2c_fd, address);

	// if(i2c_transfer) {
	// /* Need to perform a combined read/write operation
	//  */
	// 	i2c_transfer = 0;
	// 	if (sendStop == false)
	// 		return 0;
	// 	i2c_add_to_buf(address, 1, rxBuffer, quantity);
	// 	if (!i2c_readwrite(i2c_fd)) {
	// 		rxBufferIndex = 0;
	// 		rxBufferLength = quantity;
	// 		i2c_transfer = 0;
	// 		return quantity;
	// 	} else
	// 		return 0;
	// }
	if (i2c_readbytes(i2c_fd, rxBuffer, quantity) < 0)
		return 0;
	// set rx buffer iterator vars
	rxBufferIndex = 0;
	rxBufferLength = quantity;

	return quantity;
}

uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
}

uint8_t TwoWire::requestFrom(int address, int quantity)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) true);
}

uint8_t TwoWire::requestFrom(int address, int quantity, int sendStop)
{
	return requestFrom((uint8_t) address, (uint8_t) quantity, (uint8_t) sendStop);
}

void TwoWire::beginTransmission(uint8_t address)
{
	if (i2c_fd < 0 || adapter_nr < 0)
		return;
	/* set slave address via ioctl in case we need to perform terminating
	 * write operation
	 */
	i2c_setslave(i2c_fd, address);
	// save address of target and empty buffer
	txAddress = address;
	txBufferLength = 0;
}

void TwoWire::beginTransmission(int address)
{
	beginTransmission((uint8_t) address);
}

//
//	Originally, 'endTransmission' was an f(void) function.
//	It has been modified to take one parameter indicating
//	whether or not a STOP should be performed on the bus.
//	Calling endTransmission(false) allows a sketch to
//	perform a repeated start.
//
//	WARNING: Nothing in the library keeps track of whether
//	the bus tenure has been properly ended with a STOP. It
//	is very possible to leave the bus in a hung state if
//	no call to endTransmission(true) is made. Some I2C
//	devices will behave oddly if they do not see a STOP.
//
uint8_t TwoWire::endTransmission(uint8_t sendStop)
{
	int err;
	if (sendStop == true) {

		// transmit buffer (blocking)
		if (txBufferLength > 1)
			err = i2c_writebytes(i2c_fd, txBuffer, txBufferLength);
		else if (txBufferLength == 1)
			err = i2c_writebyte(i2c_fd, *txBuffer);
		else
		/* FIXME: A zero byte transmit is typically used to check for an
		 * ACK from the slave device. I'm not sure if this is the
		 * correct way to do this.
		 */
			err = i2c_readbyte(i2c_fd);
		// empty buffer
		txBufferLength = 0;
		if (err < 0)
			return 2;
		return 0;
	} else {
	/* sendStop = false
	 * pretend we have held the bus while
	 * actually waiting for the next operation
	 */
		// i2c_add_to_buf(txAddress, 0, txBuffer, txBufferLength);
		// i2c_transfer = 1;
		return 0;
	}
}

//	This provides backwards compatibility with the original
//	definition, and expected behaviour, of endTransmission
//
uint8_t TwoWire::endTransmission(void)
{
	return endTransmission(true);
}

size_t TwoWire::write(uint8_t data)
{
	if (txBufferLength >= BUFFER_LENGTH)
		return 0;
	txBuffer[txBufferLength++] = data;
	return 1;
}

size_t TwoWire::write(const uint8_t *data, size_t quantity)
{
	for (size_t i = 0; i < quantity; ++i) {
		if (txBufferLength >= BUFFER_LENGTH)
			return i;
		txBuffer[txBufferLength++] = data[i];
	}
	return quantity;
}

int TwoWire::available(void)
{
	return rxBufferLength - rxBufferIndex;
}

int TwoWire::read(void)
{
	if (rxBufferIndex < rxBufferLength)
		return rxBuffer[rxBufferIndex++];
	return -1;
}

int TwoWire::peek(void)
{
	if (rxBufferIndex < rxBufferLength)
		return rxBuffer[rxBufferIndex];
	return -1;
}

void TwoWire::flush(void)
{
	// Do nothing, use endTransmission(..) to force
	// data transfer.
}

void TwoWire::onReceive(void(*function)(int))
{
	onReceiveCallback = function;
}

void TwoWire::onRequest(void(*function)(void)) {
	onRequestCallback = function;
}

void TwoWire::onService(void)
{
}

//#if WIRE_INTERFACES_COUNT > 0
static void Wire_Init(void)
{
}

TwoWire Wire = TwoWire(Wire_Init);

void WIRE_ISR_HANDLER(void) {
	Wire.onService();
}
//#endif

#if WIRE_INTERFACES_COUNT > 1
static void Wire1_Init(void)
{
	if ((adapter_nr = i2c_getadapter(I2C1)) < 0) {
		return;
	}
	if ((i2c_fd = i2c_openadapter) < 0) {
		return;
	}
}

TwoWire Wire1 = TwoWire(Wire1_Init);

void WIRE1_ISR_HANDLER(void) {
	Wire1.onService();
}
#endif
<|endoftext|>


<commit_before>#include "collision/notification_command.hpp"

using namespace Collision;

NotificationCommand::NotificationCommand(){

}

NotificationCommand::~NotificationCommand(){

}

void NotificationCommand::execute(){

}

void NotificationCommand::execute(Collider*, Collider*){

}
<commit_msg>Removed source file in incorrect directory<commit_after><|endoftext|>


<commit_before><commit_msg>sorting the folder tree view content<commit_after><|endoftext|>


<commit_before> /*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: accselectionhelper.cxx,v $
 *
 *  $Revision: 1.12 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-16 20:38:37 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESELECTION_HPP_
#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
#endif
#ifndef _ACCSELECTIONHELPER_HXX_
#include <accselectionhelper.hxx>
#endif

#ifndef _ACCCONTEXT_HXX
#include <acccontext.hxx>
#endif
#ifndef _ACCMAP_HXX
#include <accmap.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SHAPE_HXX
#include <svx/AccessibleShape.hxx>
#endif

#ifndef _VIEWSH_HXX
#include <viewsh.hxx>
#endif
#ifndef _FESH_HXX
#include "fesh.hxx"
#endif

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>        // for SolarMutex
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

using namespace ::com::sun::star::uno;
using ::com::sun::star::uno::RuntimeException;
using ::com::sun::star::accessibility::XAccessible;
using ::com::sun::star::accessibility::XAccessibleContext;
using ::com::sun::star::accessibility::XAccessibleSelection;
using ::com::sun::star::lang::IndexOutOfBoundsException;

SwAccessibleSelectionHelper::SwAccessibleSelectionHelper(
    SwAccessibleContext& rCtxt ) :
        rContext( rCtxt )
{
}

SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper()
{
}

SwFEShell* SwAccessibleSelectionHelper::GetFEShell()
{
    DBG_ASSERT( rContext.GetMap() != NULL, "no map?" );
    ViewShell* pViewShell = rContext.GetMap()->GetShell();
    DBG_ASSERT( pViewShell != NULL,
                "No view shell? Then what are you looking at?" );

    SwFEShell* pFEShell = NULL;
    if( pViewShell->ISA( SwFEShell ) )
    {
        pFEShell = static_cast<SwFEShell*>( pViewShell );
    }

    return pFEShell;
}

void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException()
        throw ( ::com::sun::star::lang::IndexOutOfBoundsException )
{
    Reference < XAccessibleContext > xThis( &rContext );
    Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY );
    IndexOutOfBoundsException aExcept(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
                xSelThis );                                     \
    throw aExcept;
}

//=====  XAccessibleSelection  ============================================

void SwAccessibleSelectionHelper::selectAccessibleChild(
    sal_Int32 nChildIndex )
    throw ( IndexOutOfBoundsException,
            RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Get the respective child as SwFrm (also do index checking), ...
    const SwFrmOrObj aChild = rContext.GetChild( nChildIndex );
    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    // we can only select fly frames, so we ignore (should: return
    // false) all other attempts at child selection
    sal_Bool bRet = sal_False;
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell != NULL )
    {
        const SdrObject *pObj = aChild.GetSdrObject();
        if( pObj )
        {
            bRet = rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm());
        }
    }
    // no frame shell, or no frame, or no fly frame -> can't select

    // return bRet;
}

sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected(
    sal_Int32 nChildIndex )
    throw ( IndexOutOfBoundsException,
            RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Get the respective child as SwFrm (also do index checking), ...
    const SwFrmOrObj aChild = rContext.GetChild( nChildIndex );
    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    // ... and compare to the currently selected frame
    sal_Bool bRet = sal_False;
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell )
    {
        if( aChild.GetSwFrm() != 0 )
        {
            bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm());
        }
        else
        {
            bRet = pFEShell->IsObjSelected( *aChild.GetSdrObject() );
        }
    }

    return bRet;
}

void SwAccessibleSelectionHelper::clearAccessibleSelection(  )
    throw ( RuntimeException )
{
    // return sal_False     // we can't deselect
}

void SwAccessibleSelectionHelper::selectAllAccessibleChildren(  )
    throw ( RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // We can select only one. So iterate over the children to find
    // the first we can select, and select it.

    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell )
    {
        ::std::list< SwFrmOrObj > aChildren;
        rContext.GetChildren( aChildren );

        ::std::list< SwFrmOrObj >::const_iterator aIter = aChildren.begin();
        ::std::list< SwFrmOrObj >::const_iterator aEndIter = aChildren.end();
        while( aIter != aEndIter )
        {
            const SwFrmOrObj& rChild = *aIter;
            const SdrObject *pObj = rChild.GetSdrObject();
            const SwFrm* pFrm = rChild.GetSwFrm();
            if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) )
            {
                rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm );
                if( pFrm )
                    break;
            }
            ++aIter;
        }
    }
}

sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount(  )
    throw ( RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    sal_Int32 nCount = 0;
    // Only one frame can be selected at a time, and we only frames
    // for selectable children.
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell != 0 )
    {
        const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
        if( pFlyFrm )
        {
            if( rContext.GetParent(pFlyFrm, rContext.IsInPagePreview()) ==
                rContext.GetFrm() )
            {
                nCount = 1;
            }
        }
        else
        {
            sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
            if( nSelObjs > 0 )
            {
                ::std::list< SwFrmOrObj > aChildren;
                rContext.GetChildren( aChildren );

                ::std::list< SwFrmOrObj >::const_iterator aIter =
                    aChildren.begin();
                ::std::list< SwFrmOrObj >::const_iterator aEndIter =
                    aChildren.end();
                while( aIter != aEndIter && nCount < nSelObjs )
                {
                    const SwFrmOrObj& rChild = *aIter;
                    if( rChild.GetSdrObject() && !rChild.GetSwFrm() &&
                        rContext.GetParent(rChild, rContext.IsInPagePreview())
                           == rContext.GetFrm() &&
                         pFEShell->IsObjSelected( *rChild.GetSdrObject() ) )
                    {
                        nCount++;
                    }
                    ++aIter;
                }
            }
        }
    }
    return nCount;
}

Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild(
    sal_Int32 nSelectedChildIndex )
    throw ( IndexOutOfBoundsException,
            RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Since the index is relative to the selected children, and since
    // there can be at most one selected frame child, the index must
    // be 0, and a selection must exist, otherwise we have to throw an
    // IndexOutOfBoundsException
    SwFEShell* pFEShell = GetFEShell();
    if( 0 == pFEShell )
        throwIndexOutOfBoundsException();

    SwFrmOrObj aChild;
    const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
    if( pFlyFrm )
    {
        if( 0 == nSelectedChildIndex &&
            rContext.GetParent(pFlyFrm, rContext.IsInPagePreview()) ==
                rContext.GetFrm() )
        {
            aChild = pFlyFrm;
        }
    }
    else
    {
        sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
        if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs )
            throwIndexOutOfBoundsException();

        ::std::list< SwFrmOrObj > aChildren;
        rContext.GetChildren( aChildren );

        ::std::list< SwFrmOrObj >::const_iterator aIter = aChildren.begin();
        ::std::list< SwFrmOrObj >::const_iterator aEndIter = aChildren.end();
        while( aIter != aEndIter && !aChild.IsValid() )
        {
            const SwFrmOrObj& rChild = *aIter;
            if( rChild.GetSdrObject() && !rChild.GetSwFrm() &&
                rContext.GetParent(rChild, rContext.IsInPagePreview()) ==
                    rContext.GetFrm() &&
                pFEShell->IsObjSelected( *rChild.GetSdrObject() ) )
            {
                if( 0 == nSelectedChildIndex )
                    aChild = rChild;
                else
                    --nSelectedChildIndex;
            }
            ++aIter;
        }
    }

    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." );
    Reference< XAccessible > xChild;
    if( aChild.GetSwFrm() )
    {
        ::vos::ORef < SwAccessibleContext > xChildImpl(
                rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(),
                sal_True ) );
        if( xChildImpl.isValid() )
        {
            xChildImpl->SetParent( &rContext );
            xChild = xChildImpl.getBodyPtr();
        }
    }
    else
    {
        ::vos::ORef < ::accessibility::AccessibleShape > xChildImpl(
                rContext.GetMap()->GetContextImpl( aChild.GetSdrObject(),
                                          &rContext, sal_True )  );
        if( xChildImpl.isValid() )
            xChild = xChildImpl.getBodyPtr();
    }
    return xChild;
}

// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
void SwAccessibleSelectionHelper::deselectAccessibleChild(
    sal_Int32 nChildIndex )
    throw ( IndexOutOfBoundsException,
            RuntimeException )
{
    // return sal_False     // we can't deselect
    if( nChildIndex < 0 ||
        nChildIndex >= rContext.GetChildCount() )
        throwIndexOutOfBoundsException();
}
<commit_msg>INTEGRATION: CWS swwarnings (1.12.222); FILE MERGED 2007/04/11 07:02:40 tl 1.12.222.1: #i69287# warning-free code<commit_after> /*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: accselectionhelper.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: hr $ $Date: 2007-09-27 08:24:02 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _COM_SUN_STAR_ACCESSIBILITY_XACCESSIBLESELECTION_HPP_
#include <com/sun/star/accessibility/XAccessibleSelection.hpp>
#endif
#ifndef _ACCSELECTIONHELPER_HXX_
#include <accselectionhelper.hxx>
#endif

#ifndef _ACCCONTEXT_HXX
#include <acccontext.hxx>
#endif
#ifndef _ACCMAP_HXX
#include <accmap.hxx>
#endif
#ifndef _SVX_ACCESSIBILITY_ACCESSIBLE_SHAPE_HXX
#include <svx/AccessibleShape.hxx>
#endif

#ifndef _VIEWSH_HXX
#include <viewsh.hxx>
#endif
#ifndef _FESH_HXX
#include "fesh.hxx"
#endif

#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>        // for SolarMutex
#endif
#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

using ::com::sun::star::accessibility::XAccessible;
using ::com::sun::star::accessibility::XAccessibleContext;
using ::com::sun::star::accessibility::XAccessibleSelection;

SwAccessibleSelectionHelper::SwAccessibleSelectionHelper(
    SwAccessibleContext& rCtxt ) :
        rContext( rCtxt )
{
}

SwAccessibleSelectionHelper::~SwAccessibleSelectionHelper()
{
}

SwFEShell* SwAccessibleSelectionHelper::GetFEShell()
{
    DBG_ASSERT( rContext.GetMap() != NULL, "no map?" );
    ViewShell* pViewShell = rContext.GetMap()->GetShell();
    DBG_ASSERT( pViewShell != NULL,
                "No view shell? Then what are you looking at?" );

    SwFEShell* pFEShell = NULL;
    if( pViewShell->ISA( SwFEShell ) )
    {
        pFEShell = static_cast<SwFEShell*>( pViewShell );
    }

    return pFEShell;
}

void SwAccessibleSelectionHelper::throwIndexOutOfBoundsException()
        throw ( lang::IndexOutOfBoundsException )
{
    Reference < XAccessibleContext > xThis( &rContext );
    Reference < XAccessibleSelection >xSelThis( xThis, UNO_QUERY );
    lang::IndexOutOfBoundsException aExcept(
                ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("index out of bounds") ),
                xSelThis );                                     \
    throw aExcept;
}

//=====  XAccessibleSelection  ============================================

void SwAccessibleSelectionHelper::selectAccessibleChild(
    sal_Int32 nChildIndex )
    throw ( lang::IndexOutOfBoundsException,
            RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Get the respective child as SwFrm (also do index checking), ...
    const SwFrmOrObj aChild = rContext.GetChild( nChildIndex );
    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    // we can only select fly frames, so we ignore (should: return
    // false) all other attempts at child selection
    sal_Bool bRet = sal_False;
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell != NULL )
    {
        const SdrObject *pObj = aChild.GetSdrObject();
        if( pObj )
        {
            bRet = rContext.Select( const_cast< SdrObject *>( pObj ), 0==aChild.GetSwFrm());
        }
    }
    // no frame shell, or no frame, or no fly frame -> can't select

    // return bRet;
}

sal_Bool SwAccessibleSelectionHelper::isAccessibleChildSelected(
    sal_Int32 nChildIndex )
    throw ( lang::IndexOutOfBoundsException,
            RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Get the respective child as SwFrm (also do index checking), ...
    const SwFrmOrObj aChild = rContext.GetChild( nChildIndex );
    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    // ... and compare to the currently selected frame
    sal_Bool bRet = sal_False;
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell )
    {
        if( aChild.GetSwFrm() != 0 )
        {
            bRet = (pFEShell->GetCurrFlyFrm() == aChild.GetSwFrm());
        }
        else
        {
            bRet = pFEShell->IsObjSelected( *aChild.GetSdrObject() );
        }
    }

    return bRet;
}

void SwAccessibleSelectionHelper::clearAccessibleSelection(  )
    throw ( RuntimeException )
{
    // return sal_False     // we can't deselect
}

void SwAccessibleSelectionHelper::selectAllAccessibleChildren(  )
    throw ( RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // We can select only one. So iterate over the children to find
    // the first we can select, and select it.

    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell )
    {
        ::std::list< SwFrmOrObj > aChildren;
        rContext.GetChildren( aChildren );

        ::std::list< SwFrmOrObj >::const_iterator aIter = aChildren.begin();
        ::std::list< SwFrmOrObj >::const_iterator aEndIter = aChildren.end();
        while( aIter != aEndIter )
        {
            const SwFrmOrObj& rChild = *aIter;
            const SdrObject *pObj = rChild.GetSdrObject();
            const SwFrm* pFrm = rChild.GetSwFrm();
            if( pObj && !(pFrm != 0 && pFEShell->IsObjSelected()) )
            {
                rContext.Select( const_cast< SdrObject *>( pObj ), 0==pFrm );
                if( pFrm )
                    break;
            }
            ++aIter;
        }
    }
}

sal_Int32 SwAccessibleSelectionHelper::getSelectedAccessibleChildCount(  )
    throw ( RuntimeException )
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    sal_Int32 nCount = 0;
    // Only one frame can be selected at a time, and we only frames
    // for selectable children.
    SwFEShell* pFEShell = GetFEShell();
    if( pFEShell != 0 )
    {
        const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
        if( pFlyFrm )
        {
            if( rContext.GetParent(pFlyFrm, rContext.IsInPagePreview()) ==
                rContext.GetFrm() )
            {
                nCount = 1;
            }
        }
        else
        {
            sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
            if( nSelObjs > 0 )
            {
                ::std::list< SwFrmOrObj > aChildren;
                rContext.GetChildren( aChildren );

                ::std::list< SwFrmOrObj >::const_iterator aIter =
                    aChildren.begin();
                ::std::list< SwFrmOrObj >::const_iterator aEndIter =
                    aChildren.end();
                while( aIter != aEndIter && nCount < nSelObjs )
                {
                    const SwFrmOrObj& rChild = *aIter;
                    if( rChild.GetSdrObject() && !rChild.GetSwFrm() &&
                        rContext.GetParent(rChild, rContext.IsInPagePreview())
                           == rContext.GetFrm() &&
                         pFEShell->IsObjSelected( *rChild.GetSdrObject() ) )
                    {
                        nCount++;
                    }
                    ++aIter;
                }
            }
        }
    }
    return nCount;
}

Reference<XAccessible> SwAccessibleSelectionHelper::getSelectedAccessibleChild(
    sal_Int32 nSelectedChildIndex )
    throw ( lang::IndexOutOfBoundsException,
            RuntimeException)
{
    vos::OGuard aGuard(Application::GetSolarMutex());

    // Since the index is relative to the selected children, and since
    // there can be at most one selected frame child, the index must
    // be 0, and a selection must exist, otherwise we have to throw an
    // lang::IndexOutOfBoundsException
    SwFEShell* pFEShell = GetFEShell();
    if( 0 == pFEShell )
        throwIndexOutOfBoundsException();

    SwFrmOrObj aChild;
    const SwFlyFrm *pFlyFrm = pFEShell->GetCurrFlyFrm();
    if( pFlyFrm )
    {
        if( 0 == nSelectedChildIndex &&
            rContext.GetParent(pFlyFrm, rContext.IsInPagePreview()) ==
                rContext.GetFrm() )
        {
            aChild = pFlyFrm;
        }
    }
    else
    {
        sal_uInt16 nSelObjs = pFEShell->IsObjSelected();
        if( 0 == nSelObjs || nSelectedChildIndex >= nSelObjs )
            throwIndexOutOfBoundsException();

        ::std::list< SwFrmOrObj > aChildren;
        rContext.GetChildren( aChildren );

        ::std::list< SwFrmOrObj >::const_iterator aIter = aChildren.begin();
        ::std::list< SwFrmOrObj >::const_iterator aEndIter = aChildren.end();
        while( aIter != aEndIter && !aChild.IsValid() )
        {
            const SwFrmOrObj& rChild = *aIter;
            if( rChild.GetSdrObject() && !rChild.GetSwFrm() &&
                rContext.GetParent(rChild, rContext.IsInPagePreview()) ==
                    rContext.GetFrm() &&
                pFEShell->IsObjSelected( *rChild.GetSdrObject() ) )
            {
                if( 0 == nSelectedChildIndex )
                    aChild = rChild;
                else
                    --nSelectedChildIndex;
            }
            ++aIter;
        }
    }

    if( !aChild.IsValid() )
        throwIndexOutOfBoundsException();

    DBG_ASSERT( rContext.GetMap() != NULL, "We need the map." );
    Reference< XAccessible > xChild;
    if( aChild.GetSwFrm() )
    {
        ::vos::ORef < SwAccessibleContext > xChildImpl(
                rContext.GetMap()->GetContextImpl( aChild.GetSwFrm(),
                sal_True ) );
        if( xChildImpl.isValid() )
        {
            xChildImpl->SetParent( &rContext );
            xChild = xChildImpl.getBodyPtr();
        }
    }
    else
    {
        ::vos::ORef < ::accessibility::AccessibleShape > xChildImpl(
                rContext.GetMap()->GetContextImpl( aChild.GetSdrObject(),
                                          &rContext, sal_True )  );
        if( xChildImpl.isValid() )
            xChild = xChildImpl.getBodyPtr();
    }
    return xChild;
}

// --> OD 2004-11-16 #111714# - index has to be treated as global child index.
void SwAccessibleSelectionHelper::deselectAccessibleChild(
    sal_Int32 nChildIndex )
    throw ( lang::IndexOutOfBoundsException,
            RuntimeException )
{
    // return sal_False     // we can't deselect
    if( nChildIndex < 0 ||
        nChildIndex >= rContext.GetChildCount() )
        throwIndexOutOfBoundsException();
}
<|endoftext|>


<commit_before>#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include<BALL/FORMAT/readFile.h>

using namespace std;

namespace BALL
{

	char* ReadFile::getToken_(Position& pos, char delimiter) const
	{
		int len = 0;
		char* p = new char[200];

		if(pos >= strlen(line_))
		{
			Log.error() << "in getToken_ : pos too large" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && line_[pos] != delimiter)
		{
			++pos;
		}

		++pos;

		while (line_[pos] != delimiter)
		{
			if (!line_[pos])
			{
				Log.error() << "open token" << endl;
				throw ReadFileError();
			}

			p[len] = line_[pos];
			++len;
			++pos;
		}

		++pos;

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	char* ReadFile::getToken_(Position& pos) const
	{
		int len = 0;
		char* p = new char[200];

		if(pos >= strlen(line_))
		{
			Log.error() << "in getToken_ : pos too large" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && isspace(line_[pos]))
		{
			++pos;
		}

		while (line_[pos] && !isspace(line_[pos]))
		{
			p[len] = line_[pos];
			++len;
			++pos;
		}

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	char* ReadFile::getToken_() const
	{
		if (strlen(line_) > 199)
		{
			Log.error() << "line too long" << endl;
			throw ReadFileError();
		}
		int len = 0;
		int pos = 0;

		char* p = new char[200];

		if(p == 0)
		{
			Log.error() << "memory could not be assigned" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && isspace(line_[pos]))
		{
			++pos;
		}

		while (line_[pos] && !isspace(line_[pos]))
		{
			p[len] = line_[pos];
			++len;
			++pos;
		}

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	string ReadFile::copyString_(Position start, Position end) const
	{
		if (end >= strlen(line_))
		{
			Log.error() << "error in copyString_";
			throw ReadFileError();
		}
		string dest;
		for (; start <= end ; ++start)
		{
			dest += line_[start];
		}
		return dest;
	}

	int ReadFile::switch_(const vector<string>& data) const
	{
		Position i = 0;
		while (i < data.size())
		{
			if (strcmp(line_, data[i].c_str()) == 0)
			{
				return i;
			}
			++i;
		}
		return (-1);
	}

	bool ReadFile::startsWith_(const char* text) const
	{
		return (memcmp(line_, text, strlen(text)) == 0);
	}

	bool ReadFile::search_(const char* text)
	{
		while (!in.eof())
		{
			readLine_();

			if (startsWith_(text))
			{
				return true;
			}
		}
		return false;
	}

	bool ReadFile::search_(const char* text, const char* stop)
	{
		while (!in.eof())
		{
			readLine_();
			if (has_(stop))
			{
				return false;
			}

			if (startsWith_(text))
			{
				return true;
			}
		}
		return false;
	}

	void ReadFile::test_(bool condition, char* msg) const
	{
		if (condition == false)
		{
			Log.warn() << msg;
			throw ReadFileError();
		}
	}

	void ReadFile::readLine_()
	{
		in.getline(line_,200);
	}

	void ReadFile::skipLines_(int number)
	{
		for (int i = 0;  i <= number ; i++)
		{
			in.getline(line_,200);
		}
	}

	bool ReadFile::has_(const char* text) const
	{
		Position pos_line = 0;
		Position pos_line2;
		Position pos_text;
		if(strlen(line_) == 0 || strlen(text) == 0 ||
			 strlen(line_) < strlen(text) )
		{
			return false;
		}

		while (line_[pos_line])
		{
			pos_text = 0;
			pos_line2 = pos_line;
			while (text[pos_text])
			{
				if (line_[pos_line2] != text[pos_text])
				{
					break;
				}
				++pos_text;
				++pos_line2;
			}

			if (!text[pos_text])
			{
				return true;
			}

			++pos_line;
		}

		return false;
	}

} //namespace<commit_msg>fixed: warning due to missing new-line at the end of file<commit_after>#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include<BALL/FORMAT/readFile.h>

using namespace std;

namespace BALL
{

	char* ReadFile::getToken_(Position& pos, char delimiter) const
	{
		int len = 0;
		char* p = new char[200];

		if(pos >= strlen(line_))
		{
			Log.error() << "in getToken_ : pos too large" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && line_[pos] != delimiter)
		{
			++pos;
		}

		++pos;

		while (line_[pos] != delimiter)
		{
			if (!line_[pos])
			{
				Log.error() << "open token" << endl;
				throw ReadFileError();
			}

			p[len] = line_[pos];
			++len;
			++pos;
		}

		++pos;

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	char* ReadFile::getToken_(Position& pos) const
	{
		int len = 0;
		char* p = new char[200];

		if(pos >= strlen(line_))
		{
			Log.error() << "in getToken_ : pos too large" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && isspace(line_[pos]))
		{
			++pos;
		}

		while (line_[pos] && !isspace(line_[pos]))
		{
			p[len] = line_[pos];
			++len;
			++pos;
		}

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	char* ReadFile::getToken_() const
	{
		if (strlen(line_) > 199)
		{
			Log.error() << "line too long" << endl;
			throw ReadFileError();
		}
		int len = 0;
		int pos = 0;

		char* p = new char[200];

		if(p == 0)
		{
			Log.error() << "memory could not be assigned" << endl;
			throw ReadFileError();
		}

		while (line_[pos] && isspace(line_[pos]))
		{
			++pos;
		}

		while (line_[pos] && !isspace(line_[pos]))
		{
			p[len] = line_[pos];
			++len;
			++pos;
		}

		if(len == 0)
		{
			Log.error() << "token could not be read" << endl;
			throw ReadFileError();
		}

		p[len] = '\0';
		return p;
	}

	string ReadFile::copyString_(Position start, Position end) const
	{
		if (end >= strlen(line_))
		{
			Log.error() << "error in copyString_";
			throw ReadFileError();
		}
		string dest;
		for (; start <= end ; ++start)
		{
			dest += line_[start];
		}
		return dest;
	}

	int ReadFile::switch_(const vector<string>& data) const
	{
		Position i = 0;
		while (i < data.size())
		{
			if (strcmp(line_, data[i].c_str()) == 0)
			{
				return i;
			}
			++i;
		}
		return (-1);
	}

	bool ReadFile::startsWith_(const char* text) const
	{
		return (memcmp(line_, text, strlen(text)) == 0);
	}

	bool ReadFile::search_(const char* text)
	{
		while (!in.eof())
		{
			readLine_();

			if (startsWith_(text))
			{
				return true;
			}
		}
		return false;
	}

	bool ReadFile::search_(const char* text, const char* stop)
	{
		while (!in.eof())
		{
			readLine_();
			if (has_(stop))
			{
				return false;
			}

			if (startsWith_(text))
			{
				return true;
			}
		}
		return false;
	}

	void ReadFile::test_(bool condition, char* msg) const
	{
		if (condition == false)
		{
			Log.warn() << msg;
			throw ReadFileError();
		}
	}

	void ReadFile::readLine_()
	{
		in.getline(line_,200);
	}

	void ReadFile::skipLines_(int number)
	{
		for (int i = 0;  i <= number ; i++)
		{
			in.getline(line_,200);
		}
	}

	bool ReadFile::has_(const char* text) const
	{
		Position pos_line = 0;
		Position pos_line2;
		Position pos_text;
		if(strlen(line_) == 0 || strlen(text) == 0 ||
			 strlen(line_) < strlen(text) )
		{
			return false;
		}

		while (line_[pos_line])
		{
			pos_text = 0;
			pos_line2 = pos_line;
			while (text[pos_text])
			{
				if (line_[pos_line2] != text[pos_text])
				{
					break;
				}
				++pos_text;
				++pos_line2;
			}

			if (!text[pos_text])
			{
				return true;
			}

			++pos_line;
		}

		return false;
	}

} //namespace BALL
<|endoftext|>


<commit_before>/**\file
 * \ingroup example-programmes
 * \brief Matrix-esque terminal animation
 *
 * This is a terminal programme that uses libefgy's vt100 code to render a text
 * version of the matrix 'scrolling streams of text' animation. It's really
 * fairly simple but also kinda nice to see how the vt100 output is performing.
 *
 * \image html matrix.png "Screenshot of the programme running in Terminal.app"
 *
 * \copyright
 * Copyright (c) 2012-2014, ef.gy Project Members
 * \copyright
 * 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:
 * \copyright
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * \copyright
 * 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.
 *
 * \see Project Documentation: http://ef.gy/documentation/libefgy
 * \see Project Source Code: http://git.becquerel.org/jyujin/libefgy.git
 */

#include <iostream>

#include <ef.gy/vt100.h>
#include <ef.gy/random.h>
#include <chrono>
#include <csignal>
#include <cmath>
#include <sched.h>

using namespace efgy;
using namespace std::chrono;

/**\brief Data and functions related to the matrix demo
 *
 * Contains global variables and classes used by the 'matrix' demo animation.
 * This is a separate namespace to keep things all neat, clean and tidy.
 */
namespace thematrix
{
    /**\brief VT100 output buffer
     *
     * Encapsulates stdio to automatically generate the terminal escape
     * sequences to write things at specific positions with specific colours.
     */
    terminal::vt100<> output;

    /**\brief Random number generator
     *
     * A seeded instance of the mersenne twister RNG; used to position the
     * streams and to add and remove glyphs randomly.
     */
    random::mersenneTwister<> rng(1337);

    /**\brief Current time
     *
     * The point in time when processing of the current streams started; used
     * to determine when streams should be updated.
     */
    system_clock::time_point now;

    /**\brief A stream of data
     *
     * A 'stream' is what I dubbed the individual columns of text in the
     * animation. These are generated randomly and they mutate randomly as
     * well.
     */
    class stream
    {
        public:
            /**\brief A single glyph in a stream
             *
             * To create the animation, each of the glyphs in the output needs
             * to be tagges with the time it was created, in order to know
             * which colour to draw the glyph in.
             */
            class cell
            {
                public:
                    /**\brief Construct with glyph
                     *
                     * Constructs an instance of the class using the given
                     * character and the current system time.
                     *
                     * \param[in] pCharacter A unicode code point.
                     */
                    cell(const unsigned long &pCharacter)
                        : character(pCharacter), created(now) {}

                    /**\brief The glyph
                     *
                     * This is the glyph to output; must be a valid unicode
                     * glyph as the vt100 code will expect one to send to the
                     * terminal.
                     */
                    unsigned long character;

                    /**\brief When was this object created?
                     *
                     * Contains the time point of this object's creation; used
                     * to determine the colour of the glyph in the output;
                     */
                    system_clock::time_point created;
            };

            /**\brief Construct with position
             *
             * Initialises an instance of the class given the line and column
             * of where the stream should appear.
             *
             * \param[in] pLine   The line at which to create the stream; must
             *                    be less than output.size()[1].
             * \param[in] pColumn The column at which to create the stream;
             *                    must be less than output.size()[0].
             */
            stream(const std::size_t &pLine, const std::size_t &pColumn)
                : line(pLine), column(pColumn), last(now), doDelete(false) {}

            /**\brief Line component of stream position
             *
             * This is the line at which the stream is rendered to the
             * terminal.
             */
            std::size_t line;

            /**\brief Column component of stream position
             *
             * This is the column at which the stream is rendered to the
             * terminal.
             */
            std::size_t column;

            /**\brief The stream contents to render
             *
             * A vector of glyphs and the time at which they were inserted into
             * the stream; this vector is placed vertically at the coordinates
             * given by line and column. Recent glyphs are rendered in white,
             * older ones in green.
             */
            std::vector<cell> data;

            /**\brief Time of last update
             *
             * Records the last time a glyph was inserted into or removed from
             * the stream; used to determine when to add new glyphs.
             */
            system_clock::time_point last;

            /**\brief Should this stream be deleted?
             *
             * Set to true when the upper part of the stream reaches the bottom
             * of the screen; the stream should then be deleted in the main
             * loop because it won't produce any output on the screen when this
             * happens.
             */
            bool doDelete;

            /**\brief Update and render stream
             *
             * Render the current contents of the stream to the screen; if it
             * so happens that enough time has passed since the last time this
             * method was called then this function will also randomly add or
             * remove glyphs, or move the stream further down.
             *
             * \returns 'true' if the update went smoothly; 'false' otherwise.
             *          There is currently no way this function can fail, so
             *          at the moment it will always return 'true'.
             */
            bool update (void)
            {
                if ((now - last) > std::chrono::milliseconds(10))
                {
                    last = now;
                    switch (rng() % 3)
                    {
                        case 0:
                            if (data.size() > 0)
                            {
                                data.erase(data.begin() + (rng() % data.size()));
                                break;
                            }
                        default:
                            data.push_back(cell(rng() % (1 << 7)));
                    }
                }
                std::array<std::size_t,2> s = output.size();
                if (data.size() > (s[1]/2))
                {
                    if (line < s[1])
                    {
                        if (rng() % 5 == 0)
                        {
                            output.target[line][column].content = ' ';
                            line++;
                        }
                    }
                    else
                    {
                        doDelete = true;
                    }
                    data.erase(data.begin());
                }
                int i = line;
                for (cell &d : data)
                {
                    if (i >= s[1])
                    {
                        break;
                    }
                    output.target[i][column].content = d.character;
                    output.target[i][column].foregroundColour = (now - d.created) > std::chrono::milliseconds(120) ? 2 : 7;
                    output.target[i][column].backgroundColour = 0;
                    i++;
                }
                return true;
            }
    };

    /**\brief SIGINT handler
     *
     * Signal handler that calls exit() properly; the SIGINT handler is
     * replaced by this function. While SIGINT would ordinarily terminate the
     * programme anyway, it doesn't do so with a proper call to exit(), meaning
     * that destructors will not be called, further meaning that the terminal
     * can't be reset to a proper state by the terminal handling code, because
     * not using exit() properly means destructors won't run.
     */
    void handle_interrupt(int signal)
    {
        exit(0);
    }

    /**\brief Green-tinted post processing function
     *
     * A simple post-processing function for the vt100 code, which makes sure
     * that any output cell is always either white or green. This makes it
     * easier for the optimiser as it won't have to switch colours quite as
     * often as it otherwise might.
     */
    terminal::cell<long> postProcess
        (const terminal::terminal<long>&t,
         const std::size_t &l,
         const std::size_t &c)
    {
        terminal::cell<long> rv = t.target[l][c];
        rv.content = rv.content == 0 ? ' ' : rv.content;
        rv.foregroundColour = rv.foregroundColour == 7 ? 7 : 2;
        rv.backgroundColour = 0;
        return rv;
    }

    /**\brief Alternative post processing function
     *
     * Adds some curviness to the output by modifying the input coordinates a
     * bit before creating the output. Kinda looks funky, but not really
     * matrix-y. You'll have to modify the main() function yourself if you want
     * to see this in action.
     */
    terminal::cell<long> postProcessPolar
        (const terminal::terminal<long>&t,
         const std::size_t &pl,
         const std::size_t &pc)
    {
        double l = pl;
        double c = pc;
        std::array<std::size_t,2> s = t.size();
        double hl = s[1]/2;
        double hc = s[0]/2;
        double loff = l - hl;
        double coff = c - hc;
        double r2 = loff*loff + coff*coff;
        double r = std::sqrt(r2);
        l = hl + loff + std::sin(r) * 1.0;
        c = hc + coff + std::cos(r) * 1.0;
        const std::size_t tl = (std::size_t)l < s[1] ? (std::size_t)l : (s[1] - 1);
        const std::size_t tc = (std::size_t)c < s[0] ? (std::size_t)c : (s[0] - 1);
        terminal::cell<long> rv = t.target[tl][tc];
        terminal::cell<long> cv = t.current[tl][tc];
        rv.content = rv.content == 0 ? (cv.content == 0 ? ' ' : cv.content) : rv.content;
        rv.foregroundColour = rv.foregroundColour == 7 ? 7 : 2;
        rv.backgroundColour = 0;
        return rv;
    }
};

using namespace thematrix;

/**\brief Matrix demo main function
 *
 * Entry point for the matrix programme; resizes the output buffer to encompass
 * the whole terminal, sets up a SIGINT handler and then maintains a vector of
 * thematrix::stream objects at random positions.
 *
 * Use CTRL+C to terminate the programme.
 *
 * \note Command line arguments and the programme environment are ignored.
 *
 * \returns 0 for 'success', but this should never be reached as the SIGINT
 *          handler calls exit(), which is the only way to break out of the main
 *          loop.
 */
int main (int, char **)
{
    output.resize(output.getOSDimensions());
    std::array<std::size_t,2> s = output.size();

    std::size_t i;

    std::vector<stream> streams;

    std::signal(SIGINT, handle_interrupt);

    while (1)
    {
        i++;
        now = system_clock::now();

        if ((streams.size() <= 100) && (i % 50 == 0))
        {
            std::size_t l = rng() % (s[1] / 3);
            std::size_t c = rng() %  s[0];
            streams.push_back(stream(l, c));
        }

        for (stream &s : streams)
        {
            s.update();
        }

        for (unsigned int i = 0; i < streams.size(); i++)
        {
            if (streams[i].doDelete)
            {
                streams.erase(streams.begin() + i);
            }
        }

        if (output.flush(postProcess) == 0)
        {
            sched_yield();
        }
    }

    while ((i = output.flush(postProcess)) > 0);

    return 0;
}
<commit_msg>use the correct RNG for the matrix demo<commit_after>/**\file
 * \ingroup example-programmes
 * \brief Matrix-esque terminal animation
 *
 * This is a terminal programme that uses libefgy's vt100 code to render a text
 * version of the matrix 'scrolling streams of text' animation. It's really
 * fairly simple but also kinda nice to see how the vt100 output is performing.
 *
 * \image html matrix.png "Screenshot of the programme running in Terminal.app"
 *
 * \copyright
 * Copyright (c) 2012-2014, ef.gy Project Members
 * \copyright
 * 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:
 * \copyright
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * \copyright
 * 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.
 *
 * \see Project Documentation: http://ef.gy/documentation/libefgy
 * \see Project Source Code: http://git.becquerel.org/jyujin/libefgy.git
 */

#include <iostream>

#include <ef.gy/vt100.h>
#include <chrono>
#include <csignal>
#include <cmath>
#include <sched.h>
#include <random>

using namespace efgy;
using namespace std::chrono;

/**\brief Data and functions related to the matrix demo
 *
 * Contains global variables and classes used by the 'matrix' demo animation.
 * This is a separate namespace to keep things all neat, clean and tidy.
 */
namespace thematrix
{
    /**\brief VT100 output buffer
     *
     * Encapsulates stdio to automatically generate the terminal escape
     * sequences to write things at specific positions with specific colours.
     */
    terminal::vt100<> output;

    /**\brief Random number generator
     *
     * A seeded instance of the mersenne twister RNG; used to position the
     * streams and to add and remove glyphs randomly.
     */
    std::mt19937 rng(1337);

    /**\brief Current time
     *
     * The point in time when processing of the current streams started; used
     * to determine when streams should be updated.
     */
    system_clock::time_point now;

    /**\brief A stream of data
     *
     * A 'stream' is what I dubbed the individual columns of text in the
     * animation. These are generated randomly and they mutate randomly as
     * well.
     */
    class stream
    {
        public:
            /**\brief A single glyph in a stream
             *
             * To create the animation, each of the glyphs in the output needs
             * to be tagges with the time it was created, in order to know
             * which colour to draw the glyph in.
             */
            class cell
            {
                public:
                    /**\brief Construct with glyph
                     *
                     * Constructs an instance of the class using the given
                     * character and the current system time.
                     *
                     * \param[in] pCharacter A unicode code point.
                     */
                    cell(const unsigned long &pCharacter)
                        : character(pCharacter), created(now) {}

                    /**\brief The glyph
                     *
                     * This is the glyph to output; must be a valid unicode
                     * glyph as the vt100 code will expect one to send to the
                     * terminal.
                     */
                    unsigned long character;

                    /**\brief When was this object created?
                     *
                     * Contains the time point of this object's creation; used
                     * to determine the colour of the glyph in the output;
                     */
                    system_clock::time_point created;
            };

            /**\brief Construct with position
             *
             * Initialises an instance of the class given the line and column
             * of where the stream should appear.
             *
             * \param[in] pLine   The line at which to create the stream; must
             *                    be less than output.size()[1].
             * \param[in] pColumn The column at which to create the stream;
             *                    must be less than output.size()[0].
             */
            stream(const std::size_t &pLine, const std::size_t &pColumn)
                : line(pLine), column(pColumn), last(now), doDelete(false) {}

            /**\brief Line component of stream position
             *
             * This is the line at which the stream is rendered to the
             * terminal.
             */
            std::size_t line;

            /**\brief Column component of stream position
             *
             * This is the column at which the stream is rendered to the
             * terminal.
             */
            std::size_t column;

            /**\brief The stream contents to render
             *
             * A vector of glyphs and the time at which they were inserted into
             * the stream; this vector is placed vertically at the coordinates
             * given by line and column. Recent glyphs are rendered in white,
             * older ones in green.
             */
            std::vector<cell> data;

            /**\brief Time of last update
             *
             * Records the last time a glyph was inserted into or removed from
             * the stream; used to determine when to add new glyphs.
             */
            system_clock::time_point last;

            /**\brief Should this stream be deleted?
             *
             * Set to true when the upper part of the stream reaches the bottom
             * of the screen; the stream should then be deleted in the main
             * loop because it won't produce any output on the screen when this
             * happens.
             */
            bool doDelete;

            /**\brief Update and render stream
             *
             * Render the current contents of the stream to the screen; if it
             * so happens that enough time has passed since the last time this
             * method was called then this function will also randomly add or
             * remove glyphs, or move the stream further down.
             *
             * \returns 'true' if the update went smoothly; 'false' otherwise.
             *          There is currently no way this function can fail, so
             *          at the moment it will always return 'true'.
             */
            bool update (void)
            {
                if ((now - last) > std::chrono::milliseconds(10))
                {
                    last = now;
                    switch (rng() % 3)
                    {
                        case 0:
                            if (data.size() > 0)
                            {
                                data.erase(data.begin() + (rng() % data.size()));
                                break;
                            }
                        default:
                            data.push_back(cell(rng() % (1 << 7)));
                    }
                }
                std::array<std::size_t,2> s = output.size();
                if (data.size() > (s[1]/2))
                {
                    if (line < s[1])
                    {
                        if (rng() % 5 == 0)
                        {
                            output.target[line][column].content = ' ';
                            line++;
                        }
                    }
                    else
                    {
                        doDelete = true;
                    }
                    data.erase(data.begin());
                }
                int i = line;
                for (cell &d : data)
                {
                    if (i >= s[1])
                    {
                        break;
                    }
                    output.target[i][column].content = d.character;
                    output.target[i][column].foregroundColour = (now - d.created) > std::chrono::milliseconds(120) ? 2 : 7;
                    output.target[i][column].backgroundColour = 0;
                    i++;
                }
                return true;
            }
    };

    /**\brief SIGINT handler
     *
     * Signal handler that calls exit() properly; the SIGINT handler is
     * replaced by this function. While SIGINT would ordinarily terminate the
     * programme anyway, it doesn't do so with a proper call to exit(), meaning
     * that destructors will not be called, further meaning that the terminal
     * can't be reset to a proper state by the terminal handling code, because
     * not using exit() properly means destructors won't run.
     */
    void handle_interrupt(int signal)
    {
        exit(0);
    }

    /**\brief Green-tinted post processing function
     *
     * A simple post-processing function for the vt100 code, which makes sure
     * that any output cell is always either white or green. This makes it
     * easier for the optimiser as it won't have to switch colours quite as
     * often as it otherwise might.
     */
    terminal::cell<long> postProcess
        (const terminal::terminal<long>&t,
         const std::size_t &l,
         const std::size_t &c)
    {
        terminal::cell<long> rv = t.target[l][c];
        rv.content = rv.content == 0 ? ' ' : rv.content;
        rv.foregroundColour = rv.foregroundColour == 7 ? 7 : 2;
        rv.backgroundColour = 0;
        return rv;
    }

    /**\brief Alternative post processing function
     *
     * Adds some curviness to the output by modifying the input coordinates a
     * bit before creating the output. Kinda looks funky, but not really
     * matrix-y. You'll have to modify the main() function yourself if you want
     * to see this in action.
     */
    terminal::cell<long> postProcessPolar
        (const terminal::terminal<long>&t,
         const std::size_t &pl,
         const std::size_t &pc)
    {
        double l = pl;
        double c = pc;
        std::array<std::size_t,2> s = t.size();
        double hl = s[1]/2;
        double hc = s[0]/2;
        double loff = l - hl;
        double coff = c - hc;
        double r2 = loff*loff + coff*coff;
        double r = std::sqrt(r2);
        l = hl + loff + std::sin(r) * 1.0;
        c = hc + coff + std::cos(r) * 1.0;
        const std::size_t tl = (std::size_t)l < s[1] ? (std::size_t)l : (s[1] - 1);
        const std::size_t tc = (std::size_t)c < s[0] ? (std::size_t)c : (s[0] - 1);
        terminal::cell<long> rv = t.target[tl][tc];
        terminal::cell<long> cv = t.current[tl][tc];
        rv.content = rv.content == 0 ? (cv.content == 0 ? ' ' : cv.content) : rv.content;
        rv.foregroundColour = rv.foregroundColour == 7 ? 7 : 2;
        rv.backgroundColour = 0;
        return rv;
    }
};

using namespace thematrix;

/**\brief Matrix demo main function
 *
 * Entry point for the matrix programme; resizes the output buffer to encompass
 * the whole terminal, sets up a SIGINT handler and then maintains a vector of
 * thematrix::stream objects at random positions.
 *
 * Use CTRL+C to terminate the programme.
 *
 * \note Command line arguments and the programme environment are ignored.
 *
 * \returns 0 for 'success', but this should never be reached as the SIGINT
 *          handler calls exit(), which is the only way to break out of the main
 *          loop.
 */
int main (int, char **)
{
    output.resize(output.getOSDimensions());
    std::array<std::size_t,2> s = output.size();

    std::size_t i;

    std::vector<stream> streams;

    std::signal(SIGINT, handle_interrupt);

    while (1)
    {
        i++;
        now = system_clock::now();

        if ((streams.size() <= 100) && (i % 50 == 0))
        {
            std::size_t l = rng() % (s[1] / 3);
            std::size_t c = rng() %  s[0];
            streams.push_back(stream(l, c));
        }

        for (stream &s : streams)
        {
            s.update();
        }

        for (unsigned int i = 0; i < streams.size(); i++)
        {
            if (streams[i].doDelete)
            {
                streams.erase(streams.begin() + i);
            }
        }

        if (output.flush(postProcess) == 0)
        {
            sched_yield();
        }
    }

    while ((i = output.flush(postProcess)) > 0);

    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <typeinfo>
#include <stdexcept>
#include <cstdlib>
#include <ctype.h>

#define PRINT_LINE (std::cout << "line: " << __LINE__ << std::endl)

// cons must be pure list
#define EACH_CONS(var, init) for(Cons* var = regard<Cons>(init) ; typeid(*var) != typeid(Nil) ; var = (Cons*)regard<Cons>(var)->cdr)

// for debug
using std::cout;
using std::endl;

enum TokenType{
  TOKEN_BRACKET_OPEN,
  TOKEN_BRACKET_CLOSE,
  TOKEN_SYMBOL,
  TOKEN_STRING,
  TOKEN_INTEGER,
  TOKEN_NIL,
};

class Token {
public:
  TokenType type;
  std::string value;

  Token(TokenType atype) : type(atype), value(std::string()) {
  }

  Token(TokenType atype, std::string avalue) : type(atype), value(avalue) {
  }

  std::string str() {
    std::stringstream ss;
    ss << "Token(" << type << ", " << value << ")";
    return ss.str();
  }
};

namespace Lisp {
  class Expression;
}

// memory allocated exprs
std::list<Lisp::Expression*> objects;

namespace Lisp {
  class Expression {
  public:
    Expression() {
      objects.push_back(this);
    }
    virtual ~Expression() {}

    virtual std::string lisp_str() = 0;
  };

  class String : public Expression {
  public:
    std::string value;

    String(std::string &avalue) : value(avalue) {}

    std::string lisp_str() { return '"' + value + '"'; }
  };

  class Integer : public Expression {
  public:
    unsigned long value;

    Integer(std::string &avalue)  : value(std::atol(avalue.c_str())) {}
    Integer(unsigned long avalue) : value(avalue) {}

    std::string lisp_str() { return std::to_string(value); }
  };

  class Symbol : public Expression {
  public:
    std::string value;

    Symbol(std::string avalue) : value(avalue) {}

    std::string lisp_str() { return value; }
  };

  // TODO: RubyみたくExpression*に埋め込みたい
  class Nil : public Expression {
  public:
    Nil() {}

    std::string lisp_str() { return "nil"; }
  };

  class Cons : public Expression {
  public:
    Expression *car, *cdr;

    Cons(Expression* acar, Expression* acdr) : car(acar), cdr(acdr) {}

    std::string lisp_str() {
      return lisp_str_child(true);
    }

    Expression* get(size_t index) {
      if(index == 0) return car;
      else {
        if(typeid(*cdr) == typeid(Cons)) {
          return ((Cons*)cdr)->get(index - 1);
        }
        else {
          //TODO: raise range error
          return nullptr;
        }
      }
    }

    Cons* tail(size_t index) {
      if(index <= 1) return (Cons*)cdr; //TODO: regard使う
      else return (Cons*)tail(index - 1)->cdr;
    }

  private:
    std::string lisp_str_child(bool show_bracket) {
      std::stringstream ss;

      if(show_bracket) ss << '(';

      if(typeid(*car) == typeid(Cons)) {
        ss << ((Cons*)car)->lisp_str_child(true);
      }
      else {
        ss << car->lisp_str();
      }

      if(typeid(*cdr) == typeid(Cons)) {
        ss << " " << ((Cons*)cdr)->lisp_str_child(false);
      }
      else if(typeid(*cdr) != typeid(Nil)){
        ss << " . "; // ドット対
        ss << cdr->lisp_str();
      }

      if(show_bracket) ss << ')';

      return ss.str();
    }
  };

  class T : public Expression {
  public:
    T() {}

    std::string lisp_str() { return "T"; }
  };

  class Parser {
  public:
    std::vector<Expression*> parse(const std::string &code) {
      tokens = tokenize(code);

      if(false) { // NOTE: for debug
        for(auto tok : tokens) {
          std::cout << tok->str() << std::endl;
        }
      }

      std::vector<Expression*> exprs;
      while(!tokens.empty()) {
        exprs.push_back(parse_expr());
      }
      return exprs;
    }

  private:
    std::list<Token*> tokens;

    inline Token* cur_token() {
      return tokens.empty() ? nullptr : tokens.front();
    }

    void consume_token() {
      auto ctoken = cur_token();
      if(ctoken) delete ctoken;

      if(!tokens.empty()) tokens.pop_front();
    }

    Expression* parse_list() {
      consume_token();
      if(cur_token()->type != TOKEN_SYMBOL) {
        //TODO: raise an error
      }

      auto first_cons = new Cons(new Nil(), new Nil());
      auto cur_cons   = first_cons;
      size_t count = 0;
      while(!tokens.empty() && cur_token()->type != TOKEN_BRACKET_CLOSE) {
        if(count != 0) {
          cur_cons->cdr = new Cons(new Nil(), new Nil());
          cur_cons = (Cons*)cur_cons->cdr;
        }
        cur_cons->car = parse_expr();

        count++;
      }

      return first_cons;
    }

    Expression* parse_expr() {
      Expression* ret;
      switch(cur_token()->type) {
        case TOKEN_BRACKET_OPEN:
          ret = parse_list();
          break;
        case TOKEN_STRING:
          ret = new String(cur_token()->value);
          break;
        case TOKEN_NIL:
          ret = new Nil();
          break;
        case TOKEN_SYMBOL:
          ret = new Symbol(cur_token()->value);
          break;
        case TOKEN_INTEGER:
          ret = new Integer(cur_token()->value);
          break;
        default:
          throw std::logic_error("unknown token: " + std::to_string(cur_token()->type));
      }
      consume_token();
      return ret;
    }

    bool is_symbol(char c) {
      return c == '!' || ('#' <= c && c <= '\'') || ('*' <= c && c <= '/') ||
            ('<' <= c && c <= '@') || isalpha(c);
    }

    bool is_number(char c) {
      return isdigit(c);
    }

    std::list<Token*> tokenize(const std::string &code) {
      std::list<Token*> tokens;

      for(size_t i = 0 ; i < code.size() - 1 ; i++) { //TODO: -1を修正(EOFっぽい?)
        char ch = code[i];
        if(ch == '(')
          tokens.push_back(new Token(TOKEN_BRACKET_OPEN));
        else if(ch == ')')
          tokens.push_back(new Token(TOKEN_BRACKET_CLOSE));
        else if(ch == '"') { // string
          i++;

          size_t token_len = 0;
          while(code[i + token_len] != '"') {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }
          tokens.push_back(new Token(TOKEN_STRING, code.substr(i, token_len)));
          i += token_len;
        }
        else if(ch == ' ' || ch == '\n')
          ;//skip
        else if(is_number(ch)) {
          size_t token_len = 0;
          while(is_number(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              // TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          tokens.push_back(new Token(TOKEN_INTEGER, token_val));

          i += token_len - 1;
        }
        else { // symbol
          size_t token_len = 0;
          while(is_symbol(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          TokenType token_type;
          if(token_val == "nil")
            token_type = TOKEN_NIL;
          else
            token_type = TOKEN_SYMBOL;

          if(token_type == TOKEN_SYMBOL)
            tokens.push_back(new Token(TOKEN_SYMBOL, token_val));
          else
            tokens.push_back(new Token(token_type));

          i += token_len - 1;
        }
      }

      return tokens;
    }
  };

  typedef std::map<std::string, Expression*> Environment;

  class Evaluator {
    std::list<Environment> envs;

    Expression* eval_expr(Expression* expr) {
      const std::type_info& id = typeid(*expr);
      if(id == typeid(Cons)) {
        auto list = (Cons*)expr;
        auto name = regard<Symbol>(list->get(0))->value;
        if(name == "print") {
          std::cout << (evaluate(list->get(1)))->lisp_str() << std::endl;
          return new Nil();
        }
        else if(name == "type") {
          return new Symbol(std::string(typeid(*list->get(1)).name()));
        }
        else if(name == "tail") {
          auto arg0  = regard<Cons>(evaluate(list->get(1)));
          auto index = regard<Integer>(evaluate(list->get(2)));
          return arg0->tail(index->value);
        }
        else if(name == "setq") {
          envs.back()[regard<Symbol>(list->get(1))->value] = list->get(2);
          return new Nil();
        }
        else if(name == "atom") {
          auto val = evaluate(list->get(1));
          if(typeid(*val) != typeid(Cons)) return new T();
          else return new Nil();
        }
        else if(name == "+") {
          Integer* sum = new Integer(0);

          EACH_CONS(cc, list->cdr) {
            sum->value += regard<Integer>(evaluate(cc->car))->value;
          }
          return sum;
        }
        else if(name == "=") {
          // TODO: 他の型にも対応させる
          auto x = regard<Integer>(list->get(1));
          auto y = regard<Integer>(list->get(2));

          return (x->value == y->value ? (Expression*)new T() : (Expression*)new Nil());
        }
        else if(name == "let") {
          Environment env;
          auto pairs = regard<Cons>(list->get(1));
          EACH_CONS(cc, pairs) {
            auto kv = regard<Cons>(cc->car);
            env[regard<Symbol>(kv->get(0))->value] = kv->get(1);
          }
          envs.push_back(env);

          Expression* ret;
          EACH_CONS(cc, list->tail(2)) {
            ret = evaluate(cc->car);
          }

          envs.pop_back();

          return ret;
        }
        else if(name == "cond") {
          EACH_CONS(cc, list->tail(1)) {
            auto pair = regard<Cons>(cc->get(0));
            if(typeid(*evaluate(pair->get(0))) != typeid(Nil)) {
              return evaluate(pair->get(1));
            }
          }

          return new Nil();
        }
        else if(name == "for") {
          auto counter_name = regard<Symbol>(list->get(1));
          auto start        = regard<Integer>(evaluate(list->get(2)));
          auto end          = regard<Integer>(evaluate(list->get(3)));
          auto body         = list->get(4);

          auto counter      = new Integer(start->value);

          Environment env;
          env[counter_name->value] = counter;
          envs.push_back(env);

          for(; counter->value < end->value ; counter->value++) {
            evaluate(body);
          }

          envs.pop_back();

          return new Nil();
        }
        else if(name == "cons") {
          auto car = evaluate(list->get(1));
          auto cdr = evaluate(list->get(2));

          return new Cons(car, cdr);
        }
        else if(name == "list") {
          EACH_CONS(cc, list->cdr) {
            //TODO: 評価する
          }
          return list->cdr;
        }
        else {
          throw std::logic_error("undefined function: " + name);
        }
      }
      else if(id == typeid(Symbol)) {
        auto name = (Symbol*)expr;
        auto env = envs.back();
        for(auto env = envs.rbegin() ; env != envs.rend() ; env++) {
          if(env->find(name->value) != env->end()) {
            return (*env)[name->value];
          }
        }
        throw std::logic_error("undefined variable: " + name->value);
      }

      return expr;
    }

  public:
    Evaluator() {
      envs.push_back(Environment());
    }

    Expression* evaluate(Expression* expr) {
      return eval_expr(expr);
    }

    template<typename T> T* regard(Expression* expr) {
      if(typeid(*expr) != typeid(T)) {
        throw std::logic_error("illeagl type error: " + expr->lisp_str() + " is not " + std::string(typeid(T).name()));
      }
      return (T*)expr;
    }
  };
}

int main() {
  using namespace std;

  string code;
  //code.reserve(1024);

  char ch;
  while((ch = cin.get()) != std::char_traits<char>::eof()) {
    code.push_back(ch);
  }

  Lisp::Parser parser;
  auto exprs = parser.parse(code);

  Lisp::Evaluator evaluator;
  for(size_t i = 0 ; i < exprs.size() ; i++) {
    exprs[i] = evaluator.evaluate(exprs[i]);
  }

  // fake GC
  for(auto expr : objects) {
    delete expr;
  }

  return 0;
}
<commit_msg>tを追加した<commit_after>#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <list>
#include <map>
#include <stack>
#include <typeinfo>
#include <stdexcept>
#include <cstdlib>
#include <ctype.h>

#define PRINT_LINE (std::cout << "line: " << __LINE__ << std::endl)

// cons must be pure list
#define EACH_CONS(var, init) for(Cons* var = regard<Cons>(init) ; typeid(*var) != typeid(Nil) ; var = (Cons*)regard<Cons>(var)->cdr)

// for debug
using std::cout;
using std::endl;

enum TokenType{
  TOKEN_BRACKET_OPEN,
  TOKEN_BRACKET_CLOSE,
  TOKEN_SYMBOL,
  TOKEN_STRING,
  TOKEN_INTEGER,
  TOKEN_NIL,
  TOKEN_T,
};

class Token {
public:
  TokenType type;
  std::string value;

  Token(TokenType atype) : type(atype), value(std::string()) {
  }

  Token(TokenType atype, std::string avalue) : type(atype), value(avalue) {
  }

  std::string str() {
    std::stringstream ss;
    ss << "Token(" << type << ", " << value << ")";
    return ss.str();
  }
};

namespace Lisp {
  class Expression;
}

// memory allocated exprs
std::list<Lisp::Expression*> objects;

namespace Lisp {
  class Expression {
  public:
    Expression() {
      objects.push_back(this);
    }
    virtual ~Expression() {}

    virtual std::string lisp_str() = 0;
  };

  class String : public Expression {
  public:
    std::string value;

    String(std::string &avalue) : value(avalue) {}

    std::string lisp_str() { return '"' + value + '"'; }
  };

  class Integer : public Expression {
  public:
    unsigned long value;

    Integer(std::string &avalue)  : value(std::atol(avalue.c_str())) {}
    Integer(unsigned long avalue) : value(avalue) {}

    std::string lisp_str() { return std::to_string(value); }
  };

  class Symbol : public Expression {
  public:
    std::string value;

    Symbol(std::string avalue) : value(avalue) {}

    std::string lisp_str() { return value; }
  };

  // TODO: RubyみたくExpression*に埋め込みたい
  class Nil : public Expression {
  public:
    Nil() {}

    std::string lisp_str() { return "nil"; }
  };

  class Cons : public Expression {
  public:
    Expression *car, *cdr;

    Cons(Expression* acar, Expression* acdr) : car(acar), cdr(acdr) {}

    std::string lisp_str() {
      return lisp_str_child(true);
    }

    Expression* get(size_t index) {
      if(index == 0) return car;
      else {
        if(typeid(*cdr) == typeid(Cons)) {
          return ((Cons*)cdr)->get(index - 1);
        }
        else {
          //TODO: raise range error
          return nullptr;
        }
      }
    }

    Cons* tail(size_t index) {
      if(index <= 1) return (Cons*)cdr; //TODO: regard使う
      else return (Cons*)tail(index - 1)->cdr;
    }

  private:
    std::string lisp_str_child(bool show_bracket) {
      std::stringstream ss;

      if(show_bracket) ss << '(';

      if(typeid(*car) == typeid(Cons)) {
        ss << ((Cons*)car)->lisp_str_child(true);
      }
      else {
        ss << car->lisp_str();
      }

      if(typeid(*cdr) == typeid(Cons)) {
        ss << " " << ((Cons*)cdr)->lisp_str_child(false);
      }
      else if(typeid(*cdr) != typeid(Nil)){
        ss << " . "; // ドット対
        ss << cdr->lisp_str();
      }

      if(show_bracket) ss << ')';

      return ss.str();
    }
  };

  class T : public Expression {
  public:
    T() {}

    std::string lisp_str() { return "T"; }
  };

  class Parser {
  public:
    std::vector<Expression*> parse(const std::string &code) {
      tokens = tokenize(code);

      if(false) { // NOTE: for debug
        for(auto tok : tokens) {
          std::cout << tok->str() << std::endl;
        }
      }

      std::vector<Expression*> exprs;
      while(!tokens.empty()) {
        exprs.push_back(parse_expr());
      }
      return exprs;
    }

  private:
    std::list<Token*> tokens;

    inline Token* cur_token() {
      return tokens.empty() ? nullptr : tokens.front();
    }

    void consume_token() {
      auto ctoken = cur_token();
      if(ctoken) delete ctoken;

      if(!tokens.empty()) tokens.pop_front();
    }

    Expression* parse_list() {
      consume_token();
      if(cur_token()->type != TOKEN_SYMBOL) {
        //TODO: raise an error
      }

      auto first_cons = new Cons(new Nil(), new Nil());
      auto cur_cons   = first_cons;
      size_t count = 0;
      while(!tokens.empty() && cur_token()->type != TOKEN_BRACKET_CLOSE) {
        if(count != 0) {
          cur_cons->cdr = new Cons(new Nil(), new Nil());
          cur_cons = (Cons*)cur_cons->cdr;
        }
        cur_cons->car = parse_expr();

        count++;
      }

      return first_cons;
    }

    Expression* parse_expr() {
      Expression* ret;
      switch(cur_token()->type) {
        case TOKEN_BRACKET_OPEN:
          ret = parse_list();
          break;
        case TOKEN_STRING:
          ret = new String(cur_token()->value);
          break;
        case TOKEN_NIL:
          ret = new Nil();
          break;
        case TOKEN_T:
          ret = new T();
          break;
        case TOKEN_SYMBOL:
          ret = new Symbol(cur_token()->value);
          break;
        case TOKEN_INTEGER:
          ret = new Integer(cur_token()->value);
          break;
        default:
          throw std::logic_error("unknown token: " + std::to_string(cur_token()->type));
      }
      consume_token();
      return ret;
    }

    bool is_symbol(char c) {
      return c == '!' || ('#' <= c && c <= '\'') || ('*' <= c && c <= '/') ||
            ('<' <= c && c <= '@') || isalpha(c);
    }

    bool is_number(char c) {
      return isdigit(c);
    }

    std::list<Token*> tokenize(const std::string &code) {
      std::list<Token*> tokens;

      for(size_t i = 0 ; i < code.size() - 1 ; i++) { //TODO: -1を修正(EOFっぽい?)
        char ch = code[i];
        if(ch == '(')
          tokens.push_back(new Token(TOKEN_BRACKET_OPEN));
        else if(ch == ')')
          tokens.push_back(new Token(TOKEN_BRACKET_CLOSE));
        else if(ch == '"') { // string
          i++;

          size_t token_len = 0;
          while(code[i + token_len] != '"') {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }
          tokens.push_back(new Token(TOKEN_STRING, code.substr(i, token_len)));
          i += token_len;
        }
        else if(ch == ' ' || ch == '\n')
          ;//skip
        else if(is_number(ch)) {
          size_t token_len = 0;
          while(is_number(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              // TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          tokens.push_back(new Token(TOKEN_INTEGER, token_val));

          i += token_len - 1;
        }
        else { // symbol
          size_t token_len = 0;
          while(is_symbol(code[i + token_len])) {
            token_len++;
            if(i + token_len >= code.size()) {
              //TODO: raise an error
            }
          }

          std::string token_val = code.substr(i, token_len);
          TokenType token_type;
          if(token_val == "nil")
            token_type = TOKEN_NIL;
          else if(token_val == "t")
            token_type = TOKEN_T;
          else
            token_type = TOKEN_SYMBOL;

          if(token_type == TOKEN_SYMBOL)
            tokens.push_back(new Token(TOKEN_SYMBOL, token_val));
          else
            tokens.push_back(new Token(token_type));

          i += token_len - 1;
        }
      }

      return tokens;
    }
  };

  typedef std::map<std::string, Expression*> Environment;

  class Evaluator {
    std::list<Environment> envs;

    Expression* eval_expr(Expression* expr) {
      const std::type_info& id = typeid(*expr);
      if(id == typeid(Cons)) {
        auto list = (Cons*)expr;
        auto name = regard<Symbol>(list->get(0))->value;
        if(name == "print") {
          std::cout << (evaluate(list->get(1)))->lisp_str() << std::endl;
          return new Nil();
        }
        else if(name == "type") {
          return new Symbol(std::string(typeid(*list->get(1)).name()));
        }
        else if(name == "tail") {
          auto arg0  = regard<Cons>(evaluate(list->get(1)));
          auto index = regard<Integer>(evaluate(list->get(2)));
          return arg0->tail(index->value);
        }
        else if(name == "setq") {
          envs.back()[regard<Symbol>(list->get(1))->value] = list->get(2);
          return new Nil();
        }
        else if(name == "atom") {
          auto val = evaluate(list->get(1));
          if(typeid(*val) != typeid(Cons)) return new T();
          else return new Nil();
        }
        else if(name == "+") {
          Integer* sum = new Integer(0);

          EACH_CONS(cc, list->cdr) {
            sum->value += regard<Integer>(evaluate(cc->car))->value;
          }
          return sum;
        }
        else if(name == "=") {
          // TODO: 他の型にも対応させる
          auto x = regard<Integer>(list->get(1));
          auto y = regard<Integer>(list->get(2));

          return (x->value == y->value ? (Expression*)new T() : (Expression*)new Nil());
        }
        else if(name == "let") {
          Environment env;
          auto pairs = regard<Cons>(list->get(1));
          EACH_CONS(cc, pairs) {
            auto kv = regard<Cons>(cc->car);
            env[regard<Symbol>(kv->get(0))->value] = kv->get(1);
          }
          envs.push_back(env);

          Expression* ret;
          EACH_CONS(cc, list->tail(2)) {
            ret = evaluate(cc->car);
          }

          envs.pop_back();

          return ret;
        }
        else if(name == "cond") {
          EACH_CONS(cc, list->tail(1)) {
            auto pair = regard<Cons>(cc->get(0));
            if(typeid(*evaluate(pair->get(0))) != typeid(Nil)) {
              return evaluate(pair->get(1));
            }
          }

          return new Nil();
        }
        else if(name == "for") {
          auto counter_name = regard<Symbol>(list->get(1));
          auto start        = regard<Integer>(evaluate(list->get(2)));
          auto end          = regard<Integer>(evaluate(list->get(3)));
          auto body         = list->get(4);

          auto counter      = new Integer(start->value);

          Environment env;
          env[counter_name->value] = counter;
          envs.push_back(env);

          for(; counter->value < end->value ; counter->value++) {
            evaluate(body);
          }

          envs.pop_back();

          return new Nil();
        }
        else if(name == "cons") {
          auto car = evaluate(list->get(1));
          auto cdr = evaluate(list->get(2));

          return new Cons(car, cdr);
        }
        else if(name == "list") {
          EACH_CONS(cc, list->cdr) {
            //TODO: 評価する
          }
          return list->cdr;
        }
        else {
          throw std::logic_error("undefined function: " + name);
        }
      }
      else if(id == typeid(Symbol)) {
        auto name = (Symbol*)expr;
        auto env = envs.back();
        for(auto env = envs.rbegin() ; env != envs.rend() ; env++) {
          if(env->find(name->value) != env->end()) {
            return (*env)[name->value];
          }
        }
        throw std::logic_error("undefined variable: " + name->value);
      }

      return expr;
    }

  public:
    Evaluator() {
      envs.push_back(Environment());
    }

    Expression* evaluate(Expression* expr) {
      return eval_expr(expr);
    }

    template<typename T> T* regard(Expression* expr) {
      if(typeid(*expr) != typeid(T)) {
        throw std::logic_error("illeagl type error: " + expr->lisp_str() + " is not " + std::string(typeid(T).name()));
      }
      return (T*)expr;
    }
  };
}

int main() {
  using namespace std;

  string code;
  //code.reserve(1024);

  char ch;
  while((ch = cin.get()) != std::char_traits<char>::eof()) {
    code.push_back(ch);
  }

  Lisp::Parser parser;
  auto exprs = parser.parse(code);

  Lisp::Evaluator evaluator;
  for(size_t i = 0 ; i < exprs.size() ; i++) {
    exprs[i] = evaluator.evaluate(exprs[i]);
  }

  // fake GC
  for(auto expr : objects) {
    delete expr;
  }

  return 0;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////
//
// The MIT License (MIT)
//
// STP - SFML TMX Parser
// Copyright (c) 2013 Manuel Sabogal
//
// 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.
//
////////////////////////////////////////////////////////////

#ifndef STP_TILESET_HPP
#define STP_TILESET_HPP

#include "STP/Config.hpp"
#include "SFML/Graphics/Texture.hpp"
#include <SFML/Graphics/Rect.hpp>
#include <string>

namespace tmx {

STP_API class TileSet {
public:
    struct tileoffset { // 0.2
        int x, y;
        tileoffset();
    };

    struct image {
        int format;
        std::string source, trans; // trans 0.2
        unsigned int width, height;
        image();
    };

    struct terraintypes { // 0.2
    };

    struct layer { // 0.2
    };

public:
    TileSet(unsigned int firstgid, const std::string& name, unsigned int tilewidth,
            unsigned int tileheight, unsigned int spacing, unsigned int margin,
            tmx::TileSet::image image, tmx::TileSet::tileoffset tileoffset);

    ~TileSet();

    sf::IntRect getTextureRect(unsigned int gid);
    const sf::Texture* getTexture();

    unsigned int getFirstGID();
    unsigned int getLastGID();

private:
    unsigned int m_firstgid, m_lastgid, m_tilewidth, m_tileheight, m_spacing, m_margin; // spacing, margin - 0.2

    std::string m_name;
    struct tmx::TileSet::image m_image;
    struct tmx::TileSet::tileoffset m_tileoffset;
    sf::Texture m_texture;
};

}

#endif // STP_TILESET_HPP
<commit_msg>More warning fixes<commit_after>////////////////////////////////////////////////////////////
//
// The MIT License (MIT)
//
// STP - SFML TMX Parser
// Copyright (c) 2013 Manuel Sabogal
//
// 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.
//
////////////////////////////////////////////////////////////

#ifndef STP_TILESET_HPP
#define STP_TILESET_HPP

#include "STP/Config.hpp"
#include "SFML/Graphics/Texture.hpp"
#include <SFML/Graphics/Rect.hpp>
#include <string>

namespace tmx {

class STP_API TileSet {
public:
    struct tileoffset { // 0.2
        int x, y;
        tileoffset();
    };

    struct image {
        int format;
        std::string source, trans; // trans 0.2
        unsigned int width, height;
        image();
    };

    struct terraintypes { // 0.2
    };

    struct layer { // 0.2
    };

public:
    TileSet(unsigned int firstgid, const std::string& name, unsigned int tilewidth,
            unsigned int tileheight, unsigned int spacing, unsigned int margin,
            tmx::TileSet::image image, tmx::TileSet::tileoffset tileoffset);

    ~TileSet();

    sf::IntRect getTextureRect(unsigned int gid);
    const sf::Texture* getTexture();

    unsigned int getFirstGID();
    unsigned int getLastGID();

private:
    unsigned int m_firstgid, m_lastgid, m_tilewidth, m_tileheight, m_spacing, m_margin; // spacing, margin - 0.2

    std::string m_name;
    struct tmx::TileSet::image m_image;
    struct tmx::TileSet::tileoffset m_tileoffset;
    sf::Texture m_texture;
};

}

#endif // STP_TILESET_HPP
<|endoftext|>