If you have comments or questions concerning this source file, discuss them in the forum.
/*
Copyright (c) 2002 Nicolai Haehnle

See the license.txt for details. If that file was not included in the
source distributions, please email <prefect@rtts.org>
*/
// lib_object.cpp -- LObject & co implementation

#include "library.h"


/*
==============
LObject::~LObject

Disconnect all signals
==============
*/
LObject::~LObject()
{
    l_connection_t *c;

    while(conns) {
        c = conns;
        conns = c->objnext;

        c->signal->RemoveConn(c);
        L_Free(c);
    }
}

/*
==============
LObject::Disconnect

Disconnect one or more signal-slot connection.
If a parameter is 0 it signifies "any"
==============
*/
void LObject::Disconnect(LSignalMgr *pSig, l_objectfn_t fn)
{
    l_connection_t **pc, *conn;

    pc = &conns;
    while(*pc) {
        conn = *pc;

        if ((pSig && conn->signal != pSig) ||
            (fn && conn->fn != fn)) {
            pc = &conn->objnext;
            continue;
        }

        conn->signal->RemoveConn(conn);
        *pc = conn->objnext;

        L_Free(conn);
    }
}

/*
==============
LObject.:RemoveConn

Unlink a connection from the object.
ONLY called by the signal manager
==============
*/
void LObject::RemoveConn(l_connection_t *conn)
{
    l_connection_t **pc;

    pc = &conns;
    while(*pc && *pc != conn)
        pc = &(*pc)->objnext;

    lassert(*pc == conn);

    *pc = conn->objnext;
}

/*
==============
LSignalMgr::~LSignalMgr

Remove all signal-slot links
==============
*/
LSignalMgr::~LSignalMgr()
{
    l_connection_t *c;

    while(conns) {
        c = conns;
        conns = c->signext;

        c->obj->RemoveConn(c);
        L_Free(c);
    }
}

/*
==============
LSignalMgr::RemoveConn

Unlink a single connection from the signal.
ONLY called from LObject
==============
*/
void LSignalMgr::RemoveConn(l_connection_t *conn)
{
    l_connection_t **pc;

    pc = &conns;
    while(*pc && *pc != conn)
        pc = &(*pc)->signext;

    lassert(*pc == conn);

    *pc = conn->signext;
}

/*
==============
LSignalMgr::AddSlot

Connect a new slot to the signal
==============
*/
void LSignalMgr::AddSlot(LObject *pObj, l_objectfn_t fn)
{
    l_connection_t *c;

    c = (l_connection_t *)L_Malloc(sizeof(l_connection_t), TAG_SIGNAL);
    c->obj = pObj;
    c->fn = fn;
    c->signal = this;

    c->signext = conns;
    conns = c;

    c->objnext = pObj->conns;
    pObj->conns = c;
}

/*
==============
LSignalMgr::DelSlot

Remove all slots matching the given criteria.
If any of the parameters is 0 it signifies match all
==============
*/
void LSignalMgr::DelSlot(LObject *pObj, l_objectfn_t fn)
{
    l_connection_t **pc, *conn;

    pc = &conns;
    while(*pc) {
        conn = *pc;

        if ((pObj && pObj != conn->obj) ||
            (fn && fn != conn->fn)) {
            pc = &conn->signext;
            continue;
        }

        conn->obj->RemoveConn(conn);
        *pc = conn->signext;

        L_Free(conn);
    }
}