/*	XGSend.cpp
 *
 *		This is the code to handle sending messages to specific
 *	XGDispatch objects
 */

/*  YAAF - Yet another application framework
 *  Copyright (C) 1997, 1998 William Edward Woody
 *  
 *  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 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 MERCHANTABIILITY 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.
 *  
 *  To contact the author, either e-mail me at woody@pandawave.com, 
 *	or write to
 *  
 *          William Edward Woody
 *          In Phase Consulting
 *          1545 Ard Eevin Avenue
 *          Glendale, CA 91202
 *
 *	Or visit us on the web at http://www.pandawave.com
 */

#include <XConfig.h>			// must be first to optimize compile on MSVC++
#include <XEvent.h>

/************************************************************************/
/*																		*/
/*	Construction/Destruction											*/
/*																		*/
/************************************************************************/

// @G"Construction/Destruction"

/*	@F"XGSend::XGSend" @I
 *
 *		Sender construction
 */

XGSend::XGSend()
{
}

/*	@F"XGSend::~XGSend" @I
 *
 *		Remove everything receiving from me
 */

XGSend::~XGSend()
{
	while (fReceive.Length()) {
		RemoveReceiver(fReceive[0].disp);
	}
}

/************************************************************************/
/*																		*/
/*	Add/Remove receiver													*/
/*																		*/
/************************************************************************/

// @G"Receiver Management"

/*	@F"XGSend::AddReceiver" @I
 *
 *		Add the receiver to my list
 */

void XGSend::AddReceiver(XGDispatch *d)
{
	long i,len;
	XGSDispRecord dr;
	
	/*
	 *	Make sure we're not already attached
	 */
	
	len = fReceive.Length();
	for (i = 0; i < len; i++) {
		if (fReceive[i].disp == d) return;
	}
	
	/*
	 *	Now attach this
	 */
	
	dr.disp = d;
	dr.mark = false;
	fReceive += dr;
	(d->fSend) += this;
}

/*	@F"XGSend::RemoveReceiver" @I
 *
 *		Remove this receiver
 */

void XGSend::RemoveReceiver(XGDispatch *d)
{
	long i,len;
	
	/*
	 *	Find in my list and remove
	 */
	
	len = fReceive.Length();
	for (i = 0; i < len; i++) {
		if (fReceive[i].disp == d) {
			fReceive.Delete(i);
			fDelMark = true;
			break;
		}
	}
	
	/*
	 *	Find me in the sender's list
	 */
	 
	len = (d->fSend).Length();
	for (i = 0; i < len; i++) {
		if ((d->fSend)[i] == this) {
			(d->fSend).Delete(i);
			break;
		}
	}
}


/************************************************************************/
/*																		*/
/*	Send messages														*/
/*																		*/
/************************************************************************/

// @G"Message dispatch"

/*	@F"XGSend::SendMessage" @I
 *
 *		Send a message to my receiver. This works, even if different
 *	objects are deleted while I do this.
 */

void XGSend::SendMessage(long msg, long arg, void *parg)
{
	long i,len;

	/*
	 *	Clear marks
	 */
		
	fDelMark = false;
	len = fReceive.Length();
	for (i = 0; i < len; i++) fReceive[i].mark = false;
	
	for (;;) {
		for (i = 0; i < len; i++) {
			if (!fReceive[i].mark) {
				fReceive[i].mark = true;
				fReceive[i].disp->DoDispatch(msg,arg,parg,false);
				if (fDelMark) break;
			}
		}
		
		if (i >= len) break;
		
		/* If we get here, a receiver was deleted. Restart this */
		len = fReceive.Length();
		fDelMark = false;
	}
}
