/*

$FILE		:	oopc.c
$VERSIONE	:	1.00
$DATA		:	Novembre 1991
$PROGETTO	:	Tecniche OOP in C, seconda soluzione
$AUTORE		:	Paolo Sommaruga
$RUOLO		:	Codifica le funzioni di supporto necessarie a tutti gli
				oggetti.
$USO		:	Linking con i files di codifica degli oggetti T2.

*/


#include "exec/exec.h"
#include "stdio.h"

#include "oopc.h"

/*-------------------------------------------------------------
	Esegui: esegue dispatch ricorsivo sui metodi fino a COMMON.
*/

static int Esegui( pOgt, pClass, Msg )
POGT  pOgt;
CLS  *pClass;
int    Msg;

{
#define METODO_EX  "Funzione di scansione metodi."
#define E_NOMETHOD "ERRORE [GRAVE]: Metodo non trovato!"

MTD   Metodo;
int  iMetodi = 0;
int   ercode = RETURN_OK;

Metodo = (pOgt->ogt_pClass->cls_pMetodi[ iMetodi ]);

if ( Metodo.mtd_Id == Msg ) /* se troviamo l'identificatore di messaggio... */
    {
    ercode = (*Metodo.mtd_Metodo)(pOgt);
    } /* if */
else                        /* ...continuiamo a scandire l'array */
    {
    if ( Metodo.mtd_Id != 0 )
        {
        iMetodi++;
        } /* if */
    else    /* array finito; e` un messaggio di superclass... */
        {
        if ( pOgt->ogt_pClass->cls_pAncestor != NULL )  /* se c'e un genitore...*/
            {
            ercode = Esegui( pOgt, pOgt->ogt_pClass->cls_pAncestor, Msg );
            } /* if */
        else
            {
			INFO_SET( METODO_EX, E_NOMETHOD );
            ercode = RETURN_FAIL;   /* niente genitore, chiamata fallita */
            } /* else */
        } /* else */
    } /* if */

return ercode;
} /* Fine di Esegui */

/*---------------------------------------------------------------
    MSG: Funzione di dispatching dei messaggi, con ereditarieta`.
*/

int MSG( pOgt, Msg )
POGT pOgt;
int   Msg;

{
return Esegui( pOgt, pOgt->ogt_pClass, Msg );
} /* Fine di MSG */

/*--------------------------------------------------------------------------
    NUOVO: Invoca la FUNCTIONP f_dispatch dell'oggetto invocato, restituendo
           il ptr all'handle dell'oggetto.

                o_nuovoggetto = NUOVO( BUFFER );
                                     ( FILE );
                                     ( FINESTRA );
                                     ( ... );
*/

POGT NUOVO( fpDispatch )
FUNCTIONP fpDispatch;

{
POGT pNewObject = NULL;
int errore;

errore = (*fpDispatch) ( pNewObject );

if (errore)
    return NULL;

return pNewObject;
} /* Fine di NUOVO */

/*-------------------------------------------------------------------------
    NSC: Nuova Struttura di Controllo. Alloca la memoria per l'handle dello
         oggetto. Chiamata dal metodo MSG_NEW_r dell'oggetto puntato, a sua
         volta invocato da NUOVO.
*/

int NSC( oNsc )
POGT oNsc;

{
#define METODO_CO "Metodo di creazione OGGETTO generico."
#define E_NOMEM_O "ERRORE: Fallita AllocMem per Struttura Controllo OGGETTO."

oNsc = (POGT)AllocMem( sizeof( OGT ) , MEMF_PUBLIC|MEMF_CLEAR );

if ( !oNsc ) {
    INFO_SET( METODO_CO , E_NOMEM_O );
    return RETURN_FAIL;
} /* if */

return RETURN_OK;
} /* Fine di NSC */

/*-------------------------
	CCLS: Copia una CLaSse.
*/

int CCLS( pFrom , pTo )
CLS *pFrom;
CLS *pTo;

{
MTD  MetodoFrom;
MTD  MetodoTo;
int iName = 0;
int  Ident = MSG_NULL;
int iMetodi = 0;

for( iName = CLASS_NAME ; iName > 0 ; iName-- )
	{
	pTo->cls_Name[ iName ] = pFrom->cls_Name[ iName ];
	} /* for */

MetodoFrom = (pFrom->cls_pMetodi[ iMetodi ]);
MetodoTo   = (  pTo->cls_pMetodi[ iMetodi ]);
Ident = MetodoFrom.mtd_Id;

while( Ident != 0 )
	{
	MetodoTo.mtd_Id     = MetodoFrom.mtd_Id;
	MetodoTo.mtd_Metodo = MetodoFrom.mtd_Metodo;

	iMetodi++;

	MetodoFrom = (pFrom->cls_pMetodi[ iMetodi ]);
	MetodoTo   = (  pTo->cls_pMetodi[ iMetodi ]);
	Ident = MetodoFrom.mtd_Id;

	} /* while */

pTo->cls_pAncestor = pFrom->cls_pAncestor;

return RETURN_OK;
} /* Fine di CCLS */

/*-------------------------------------------------------------------
    DSC: Distruggi Struttura di Controllo. De-alloca la memoria della
         Struttura di Controllo dell'oggetto. Chiamata per ultima dal
         metodo MSG_OFF dell'oggetto puntato.
*/

void DSC( oDsc )
POGT oDsc;

{
FreeMem( oDsc , sizeof (OGT ) );
} /* Fine di DSC */
