/*
 * Copyright (c) 1999 The University of Utah and
 * the Computer Systems Laboratory at the University of Utah (CSL).
 *
 * This file is part of Flick, the Flexible IDL Compiler Kit.
 *
 * Flick 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.
 *
 * Flick 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Flick; see the file COPYING.  If not, write to
 * the Free Software Foundation, 59 Temple Place #330, Boston, MA 02111, USA.
 */

#include <assert.h>
#include <stdlib.h>
#include <string.h>

#include <mom/compiler.h>
#include <mom/pres_c.h>
#include <mom/c/be/be_looper.hh>

be_handler::be_handler()
{
	this->name = "";
	this->pri = 0;
	this->handler = 0;
}

be_handler::be_handler(const char *the_name, int the_pri,
		       struct be_event *(*the_handler)(struct be_handler *bh,
						       struct be_event *be))
	: name(the_name), pri(the_pri), handler(the_handler)
{
}

be_handler::~be_handler()
{
}

void be_handler::set_parent(struct be_looper *the_parent)
{
	this->parent = the_parent;
}

struct be_looper *be_handler::get_parent()
{
	return( this->parent );
}

struct be_event *be_handler::handle(struct be_event *be)
{
	return( this->handler(this, be) );
}

be_looper::be_looper()
{
	new_list(&this->handlers);
	new_list(&this->event_queue);
}

be_looper::be_looper(const char *the_name, int the_pri)
	: be_handler(the_name, the_pri, 0)
{
	new_list(&this->handlers);
	new_list(&this->event_queue);
}

be_looper::~be_looper()
{
}

void be_looper::add_handler(struct be_handler *bh)
{
	struct be_handler *curr;
	int done = 0;

	curr = (struct be_handler *)this->handlers.head;
	while( curr->succ && !done ) {
		if( bh->pri > curr->pri ) {
			insert_node(curr->pred, bh);
			done = 1;
		}
		curr = (struct be_handler *)curr->succ;
	}
	if( !done )
		add_tail(&this->handlers, bh);
	bh->set_parent(this);
}

struct be_handler *be_looper::find_handler(const char *the_name)
{
	struct be_handler *bh, *retval = 0;
	
	bh = (struct be_handler *)this->handlers.head;
	while( bh->succ && !retval ) {
		if( !strcmp(the_name, bh->name) )
			retval = bh;
		bh = (struct be_handler *)bh->succ;
	}
	return( retval );
}

void be_looper::queue_event(struct be_event *be)
{
	add_tail(&this->event_queue, &be->link);
}

struct be_event *be_looper::vmake_event(int id, va_list /*args*/)
{
	struct be_event *be;
	
	be = new be_event;
	be->id = id;
	return( be );
}

struct be_event *be_looper::make_event(int id, ...)
{
	struct be_event *retval;
	va_list args;
	
	va_start(args, id);
	retval = this->vmake_event(id, args);
	va_end(args);
	return( retval );
}

struct be_event *be_looper::handle(struct be_event *orig_be)
{
	struct be_handler *bh;
	struct be_event *be;
	
	/* Queue the event for processing */
	this->queue_event(orig_be);
	/*
	 * Handle any pending events, eventually we will get to
	 * the one passed in, and any added after it
	 */
	while( (be = (struct be_event *)rem_head(&this->event_queue)) ) {
		bh = (struct be_handler *)this->handlers.head;
		while( bh->succ && be ) {
			be = bh->handle(be);
			bh = (struct be_handler *)bh->succ;
		}
	}
	/* We return the original event since thats what the caller expects */
	return( orig_be );
}


syntax highlighted by Code2HTML, v. 0.9.1