#ifndef CODE_MESSAGE_CXX
#define CODE_MESSAGE_CXX

/*-----------------------------------------------------------------------
 * Xclasses code file
 * ($Id: message.cxx,v 1.2 1998/07/29 23:02:27 schmitzj Exp $)
 * 
 * Copyright (C) 1998 Jürgen Schmitz
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA  02111-1307, USA.
 *-----------------------------------------------------------------------
 */

#include <Xclasses/types.h>
#include "../include/callback.h"
#include <Xclasses/message.h>
#include <Xclasses/gadget.h>

struct allgadgets
{
	struct node		base;
	class gadget	*gg;
	class msg_get	*get;
	class msg_set	*set;
	class msg_conv	*getconv;
	class msg_conv	*setconv;
};

message::message() : gadgets()
{
}
message::~message()
{
	struct allgadgets *n;
	
	while (n=(allgadgets*)gadgets.RemTail())
	{
		if (n->get) delete n->get;
		if (n->set) delete n->set;
		if (n->getconv) delete n->getconv;
		if (n->setconv) delete n->setconv;
	}
}
void message::Msg(gadget *g,int t)
{
	struct allgadgets *n=(allgadgets*)gadgets.head;
	void *data=NULL,*cdata;
	
	while (n->base.next)
	{
		if (n->gg==g && n->get)
		{
			data=n->get->get();
			if (n->getconv)
				data=n->getconv->conv(data);
			n=(allgadgets*)gadgets.tail;
		}
		n=(allgadgets*)n->base.next;
	}
	if (data)
	{
		n=(allgadgets*)gadgets.head;
		while (n->base.next)
		{
			if (n->gg!=g && n->set)
			{
				if (n->setconv)
					cdata=n->setconv->conv(data);
				else
					cdata=data;
				n->set->set(cdata);
			}
			n=(allgadgets*)n->base.next;
		}
	}
}

void message::Add(gadget *g,class msg_get *get,class msg_conv *getconv,class msg_set *set,class msg_conv *setconv)
{
	struct allgadgets *n=new allgadgets;

	if (n)
	{
		n->base.text=(char*)g;
		n->gg		=g;
		n->get		=get;
		n->getconv	=getconv;
		n->set		=set;
		n->setconv	=setconv;
		gadgets.AddTail((node*)n);
		g->MessageHandler(this);
	}
}
void message::Remove(class gadget *g)
{
	struct allgadgets *n=(allgadgets*)gadgets.head;
	
	while (n->base.next)
	{
		if (n->gg==g)
		{
			n->gg->MessageHandler(NULL);
			if (n->get) delete n->get;
			if (n->set) delete n->set;
			if (n->getconv) delete n->getconv;
			if (n->setconv) delete n->setconv;
			return;
		}
		n=(allgadgets*)n->base.next;
	}
}

void message::Set(void *data)
{
	struct allgadgets *n=(allgadgets*)gadgets.head;
	void *cdata;

	while (n->base.next)
	{
		if (n->set)
		{
			if (n->setconv)
				cdata=n->setconv->conv(data);
			else
				cdata=data;
			n->set->set(cdata);
		}
		n=(allgadgets*)n->base.next;
	}
}
void *message::Get(void)
{
	struct allgadgets *n=(allgadgets*)gadgets.head;
	void *data=NULL;
	
	while (n->base.next)
	{
		if (n->get)
		{
			data=n->get->get();
			if (n->getconv)
				data=n->getconv->conv(data);
			return data;
		}
		n=(allgadgets*)n->base.next;
	}
	return NULL;
}

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

msg_get::msg_get(callable *c,void (callable::*f)(void))
{
	classptr=c;
	classfunc=f;
}
msg_get::~msg_get()
{
}
msg_set::msg_set(callable *c,void (callable::*f)(void))
{
	classptr=c;
	classfunc=f;
}
msg_set::~msg_set()
{
}
msg_conv::msg_conv()
{
}
msg_conv::~msg_conv()
{
}

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

#endif
