/*  Inti: Integrated Foundation Classes
 *  Copyright (C) 2002 The Inti Development Team.
 *  Copyright (C) 2000 Red Hat, Inc.
 *  Copyright 1999, Karl Einar Nelson
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

//! @file inti/signals.h
//! @brief C++ signal interface.
//!
//! Provides a set of signal class templates you can use to create signals
//! that can pass up to 6 arguments to signal handlers connected via the
//! slot interface (see inti/slot.h). The signal classes are named Signal0
//! to Signal6, where 0 to 6 specifies the number of arguments that can be
//! passed to a slot.

#ifndef INTI_SIGNALS_H
#define INTI_SIGNALS_H

#ifndef INTI_SLOT_H
#include <inti/slot.h>
#endif

#ifndef INTI_CONNECTION_H
#include <inti/connection.h>
#endif

#ifndef _CPP_VECTOR
#include <vector>
#endif

namespace Inti {
	
class Signal;

//! @class SlotNode signals.h inti/signals.h
//! @brief A node class for managing slots connected to Inti::Signal's.

class SlotNode : public Node
{
	friend class Signal;

	SlotNode(const Slot *slot);
	~SlotNode();

	bool is_blocked;

public:
	bool blocked() const { return is_blocked; }
	//!< Returns true if the slot is blocked.
	
	virtual void block();
	//!< Block signal emission to the slot until unblock is called.

	virtual void unblock();
	//!< Unblock the slot so signal emmissions can be received.

	virtual void disconnect();
	//!< Disconnect the slot. The slot will no longer recieve signal emissions.
};

// DefaultMarshal class (from marshal.h, libsigc++)

template <typename R>
class DefaultMarshal
{
public:
	typedef R OutType;
	typedef R InType;

private:
	OutType value_;

public:
	DefaultMarshal() :value_() {}
    
	OutType& value() { return value_; }
    
	// Return true to stop emission.
	bool marshal(const InType & newval)
	{
		value_ = newval;
		return false;
	}
};

//! @class Signal signals.h inti/signals.h
//! @brief Base class for the C++ signal interface.

class Signal
{
	Signal(const Signal&);
	Signal& operator=(const Signal&);

protected:
	typedef std::vector<SlotNode*> ConnectionList;
	//!< ConnectionList type.

	ConnectionList connection_list;
	//!< A list of all the slots connected to the signal.

public:
	Signal();
	//!< Constructor.

	virtual ~Signal();
	//!< Destructor.

	SlotNode* connect(const Slot *slot);
	//!< Creates a new SlotNode for slot and adds it to the <EM>connection_list</EM>.
};

//! @class Signal0 signals.h inti/signals.h
//! @brief A template for a signal passing no arguments and returning a value of type R.

template<typename R, typename Marshal = DefaultMarshal<R> >
class Signal0 : public Signal
{
	typedef Signal0<R> Self;

	static R callback(void *data)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit();
	}

public:
	typedef Slot0<R> SlotType;
	//!< Function signature for handlers connecting the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot0<R>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot0<Self, R>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot0<R>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit()
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call()))
					break;
			}
			++i;
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @return The value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()() 
	{
		return emit(); 
	}
	//!< Function operator; calls emit().
};

// Signal0 partially specialized for void return

template<typename IgnoreMarshal>
class Signal0<void, IgnoreMarshal> : public Signal
{
	typedef Signal0<void, IgnoreMarshal> Self;

	static void callback(void *data)
	{
		Self *s = static_cast<Self*>(data);
		s->emit();
	}

public:
	typedef Slot0<void> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot0<Self, void>(this, &callback);
	}

	void emit()
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call();
			}
			++i;
		}
	}
		
	void operator()()
	{
		emit(); 
	}
};

//! @class Signal1 signals.h inti/signals.h
//! @brief A template for a signal passing one argument of type P1 and returning a value of type R.

template<typename R, typename P1, typename Marshal = DefaultMarshal<R> >
class Signal1 : public Signal
{
	typedef Signal1<R, P1> Self;

	static R callback(void *data, P1 p1)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1);
	}

public:
	typedef Slot1<R, P1> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot1<R, P1>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot1<Self, R, P1>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot1<R, P1>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @return The value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1) 
	{
		return emit(p1); 
	}
	//!< Function operator; calls emit().
};

// Signal1 partially specialized for void return

template<typename P1, typename IgnoreMarshal>
class Signal1<void, P1, IgnoreMarshal> : public Signal
{
	typedef Signal1<void, P1, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1);
	}

public:
	typedef Slot1<void, P1> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot1<Self, void, P1>(this, &callback);
	}

	void emit(P1 p1)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1);
			}
			++i;
		}
	}
		
	void operator()(P1 p1)
	{
		emit(p1); 
	}
};

//! @class Signal2 signals.h inti/signals.h
//! @brief A template for a signal passing two arguments of type P1 and P2,
//! and returning a value of type R.

template<typename R, typename P1, typename P2, typename Marshal = DefaultMarshal<R> >
class Signal2 : public Signal
{
	typedef Signal2<R, P1, P2> Self;

	static R callback(void *data, P1 p1, P2 p2)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1, p2);
	}

public:
	typedef Slot2<R, P1, P2> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot2<R, P1, P2>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot2<Self, R, P1, P2>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot2<R, P1, P2>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1, P2 p2)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1, p2)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @param p2 Passes p2 to the signal handler.
	//!< @return The value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1, P2 p2) 
	{
		return emit(p1, p2); 
	}
	//!< Function operator; calls emit().
};

// Signal2 partially specialized for void return

template<typename P1, typename P2, typename IgnoreMarshal>
class Signal2<void, P1, P2, IgnoreMarshal> : public Signal
{
	typedef Signal2<void, P1, P2, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1, P2 p2)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1, p2);
	}

public:
	typedef Slot2<void, P1, P2> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot2<Self, void, P1, P2>(this, &callback);
	}

	void emit(P1 p1, P2 p2)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1, p2);
			}
			++i;
		}
	}
		
	void operator()(P1 p1, P2 p2)
	{
		emit(p1, p2); 
	}
};

//! @class Signal3 signals.h inti/signals.h
//! @brief A template for a signal passing three arguments of type P1, P2 and P3,
//! and returning a value of type R.

template<typename R, typename P1, typename P2, typename P3, typename Marshal = DefaultMarshal<R> >
class Signal3 : public Signal
{
	typedef Signal3<R, P1, P2, P3> Self;

	static R callback(void *data, P1 p1, P2 p2, P3 p3)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1, p2, p3);
	}

public:
	typedef Slot3<R, P1, P2, P3> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot3<R, P1, P2, P3>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot3<Self, R, P1, P2, P3>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot3<R, P1, P2, P3>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1, P2 p2, P3 p3)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1, p2, p3)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @param p2 Passes p2 to the signal handler.
	//!< @param p3 Passes p3 to the signal handler.
	//!< @return The value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1, P2 p2, P3 p3) 
	{
		return emit(p1, p2, p3); 
	}
	//!< Function operator; calls emit().
};

// Signal3 partially specialized for void return

template<typename P1, typename P2, typename P3, typename IgnoreMarshal>
class Signal3<void, P1, P2, P3, IgnoreMarshal> : public Signal
{
	typedef Signal3<void, P1, P2, P3, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1, P2 p2, P3 p3)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1, p2, p3);
	}

public:
	typedef Slot3<void, P1, P2, P3> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot3<Self, void, P1, P2, P3>(this, &callback);
	}

	void emit(P1 p1, P2 p2, P3 p3)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1, p2, p3);
			}
			++i;
		}
	}
		
	void operator()(P1 p1, P2 p2, P3 p3)
	{
		emit(p1, p2, p3); 
	}
};

//! @class Signal4 signals.h inti/signals.h
//! @brief A template for a signal passing four arguments of type P1, P2, P3 and P4,
//! and returning a value of type R.

template<typename R, typename P1, typename P2, typename P3, typename P4, typename Marshal = DefaultMarshal<R> >
class Signal4 : public Signal
{
	typedef Signal4<R, P1, P2, P3, P4> Self;

	static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1, p2, p3, p4);
	}

public:
	typedef Slot4<R, P1, P2, P3, P4> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot4<R, P1, P2, P3, P4>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot4<Self, R, P1, P2, P3, P4>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot4<R, P1, P2, P3, P4>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1, P2 p2, P3 p3, P4 p4)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1, p2, p3, p4)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @param p2 Passes p2 to the signal handler.
	//!< @param p3 Passes p3 to the signal handler.
	//!< @param p4 Passes p4 to the signal handler.
	//!< @return the value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1, P2 p2, P3 p3, P4 p4) 
	{
		return emit(p1, p2, p3, p4); 
	}
	//!< Function operator; calls emit().
};

// Signal4 partially specialized for void return

template<typename P1, typename P2, typename P3, typename P4, typename IgnoreMarshal>
class Signal4<void, P1, P2, P3, P4, IgnoreMarshal> : public Signal
{
	typedef Signal4<void, P1, P2, P3, P4, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1, p2, p3, p4);
	}

public:
	typedef Slot4<void, P1, P2, P3, P4> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot4<Self, void, P1, P2, P3, P4>(this, &callback);
	}

	void emit(P1 p1, P2 p2, P3 p3, P4 p4)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1, p2, p3, p4);
			}
			++i;
		}
	}
		
	void operator()(P1 p1, P2 p2, P3 p3, P4 p4)
	{
		emit(p1, p2, p3, p4); 
	}
};

//! @class Signal5 signals.h inti/signals.h
//! @brief A template for a signal passing five arguments of type P1, P2, P3, P4 and P5,
//! and returning a value of type R.

template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename Marshal = DefaultMarshal<R> >
class Signal5 : public Signal
{
	typedef Signal5<R, P1, P2, P3, P4, P5> Self;

	static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1, p2, p3, p4, p5);
	}

public:
	typedef Slot5<R, P1, P2, P3, P4, P5> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot5<R, P1, P2, P3, P4, P5>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot5<Self, R, P1, P2, P3, P4, P5>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot5<R, P1, P2, P3, P4, P5>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1, p2, p3, p4, p5)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @param p2 Passes p2 to the signal handler.
	//!< @param p3 Passes p3 to the signal handler.
	//!< @param p4 Passes p4 to the signal handler.
	//!< @param p5 Passes p5 to the signal handler.
	//!< @return the value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) 
	{
		return emit(p1, p2, p3, p4, p5); 
	}
	//!< Function operator; calls emit().
};

// Signal5 partially specialized for void return

template<typename P1, typename P2, typename P3, typename P4, typename P5, typename IgnoreMarshal>
class Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> : public Signal
{
	typedef Signal5<void, P1, P2, P3, P4, P5, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1, p2, p3, p4, p5);
	}

public:
	typedef Slot5<void, P1, P2, P3, P4, P5> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot5<Self, void, P1, P2, P3, P4, P5>(this, &callback);
	}

	void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1, p2, p3, p4, p5);
			}
			++i;
		}
	}
		
	void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
	{
		emit(p1, p2, p3, p4, p5); 
	}
};

//! @class Signal6 signals.h inti/signals.h
//! @brief A template for a signal passing six arguments of type P1, P2, P3, P4, P5 and P6,
//! and returning a value of type R.

template<typename R, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename Marshal = DefaultMarshal<R> >
class Signal6 : public Signal
{
	typedef Signal6<R, P1, P2, P3, P4, P5, P6> Self;

	static R callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
	{
		Self *s = static_cast<Self*>(data);
		return s->emit(p1, p2, p3, p4, p5, p6);
	}

public:
	typedef Slot6<R, P1, P2, P3, P4, P5, P6> SlotType;
	//!< Function signature for handlers connecting to the signal.

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}
	//!< Connect a slot to the signal.
	//!< @param slot A slot of type Slot6<R, P1, P2, P3, P4, P5, P6>.
	//!< @return A connection object.
	//!<
	//!< <BR>The returned connection object can be used alter or change the connection.

	SlotType* slot()
	{
		return new SignalSlot6<Self, R, P1, P2, P3, P4, P5, P6>(this, &callback);
	}
	//!< Returns a slot for this signal.
	//!< @return A new slot of type Slot6<R, P1, P2, P3, P4, P5, P6>.
	//!<
	//!< <BR>The returned slot can be passed to another signal allowing the
	//!< other signal to call this signal when it gets emitted.

	R emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
	{
		Marshal m;
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				if (m.marshal(slot->call(p1, p2, p3, p4, p5, p6)))
					break;
			}
			++i;		
		}
		return m.value();	
	}
	//!< Emit the signal.
	//!< @param p1 Passes p1 to the signal handler.
	//!< @param p2 Passes p2 to the signal handler.
	//!< @param p3 Passes p3 to the signal handler.
	//!< @param p4 Passes p4 to the signal handler.
	//!< @param p5 Passes p5 to the signal handler.
	//!< @param p6 Passes p6 to the signal handler.
	//!< @return the value returned by the signal handler.
	//!<
	//!< <BR>Calls every slot connected to this signal, in order of connection.

	R operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) 
	{
		return emit(p1, p2, p3, p4, p5, p6); 
	}
	//!< Function operator; calls emit().
};

/*  Signal6 partially specialized for void return
 */
 
template<typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename IgnoreMarshal>
class Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> : public Signal
{
	typedef Signal6<void, P1, P2, P3, P4, P5, P6, IgnoreMarshal> Self;

	static void callback(void *data, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
	{
		Self *s = static_cast<Self*>(data);
		s->emit(p1, p2, p3, p4, p5, p6);
	}

public:
	typedef Slot6<void, P1, P2, P3, P4, P5, P6> SlotType;

	Connection connect(const SlotType *slot)
	{ 
		return Signal::connect(slot);
	}

	SlotType* slot()
	{
		return new SignalSlot6<Self, void, P1, P2, P3, P4, P5, P6>(this, &callback);
	}

	void emit(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
	{
		ConnectionList::iterator i = connection_list.begin();
		while (i != connection_list.end())
		{
			if (!(*i)->blocked())
			{
				SlotType *slot = dynamic_cast<SlotType*>((*i)->slot());
				slot->call(p1, p2, p3, p4, p5, p6);
			}
			++i;
		}
	}
		
	void operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6)
	{
		emit(p1, p2, p3, p4, p5, p6); 
	}
};

} // namespace Inti

#endif // INTI_SIGNALS_H


