/*

$FILE		:	lista.c
$VERSIONE	:	1.00
$DATA		:	Novembre 1991
$PROGETTO	:	Tecniche OOP in C, prima soluzione
$AUTORE		:	Paolo Sommaruga
$RUOLO		:	File di codifica del dispatcher e dei metodi di LISTA.
$USO		:	E` il file principale dell'oggetto LISTA.

*/

#include "exec/exec.h"
#include "clib/exec_protos.h"

#include "lista.h"

typedef struct lista_data_block {
	#include "lista.p"
} LDB;

typedef struct lista_item_block {
    struct Node ltbNode;
    CADDR       ltbData;
} LTB;

/*-------------------------------------------------------------
    LISTA: Dispatcher generale per i metodi dell'oggetto LISTA.
*/

int LISTA( h_ogtIpse, msg, pParam, pResult )
POGT  h_ogtIpse;
int   msg;
CADDR pParam;
CADDR pResult;

{
int errore = 0;

    switch ( msg ) {
        case MSG_NEW_r :
            errore = M_CREA_R( (POGT)pResult );
            break;

        case MSG_ADDH_p :
            errore = M_ADDH_OP( h_ogtIpse, pParam );
            break;

        case MSG_ADDT_p :
            errore = M_ADDT_OP( h_ogtIpse, pParam );
            break;

        case MSG_REMH_r :
            errore = M_REMH_OR( h_ogtIpse, pResult );
            break;

        case MSG_REMT_r :
            errore = M_REMT_OR( h_ogtIpse, pResult );
            break;

        case MSG_REM_p :
            errore = M_REM_OP( h_ogtIpse, pParam );
            break;

        case MSG_GIVE_pr :
            errore = M_GIVE_OPR( h_ogtIpse, pParam, pResult );
            break;

        case MSG_FORALL_p :
            errore = M_FORALL_OP( h_ogtIpse, pParam );
            break;

        case MSG_OFF :
            errore = M_DIST_O( h_ogtIpse );
            break;

        default :
            errore = BASE( h_ogtIpse, msg, pParam, pResult );
            break;
    }

return errore;

} /* Fine di LISTA */

/*---------------------------------------------------------------------------
    M_CREA_R: Alloca memoria per la struttura di controllo e per l'area dati.
              Se fallisce de-alloca tutto e restituisce RETURN_FAIL.
*/

static int M_CREA_R( h_ogtNew )
POGT h_ogtNew;

{
#define METODO_CL "Metodo di creazione LISTA."
#define E_NOMEM_LD "ERRORE: Fallita AllocMem per LISTA: area dati."

int errore;

/* Assegno un ptr temporaneo con un cast per evitare casini */
LDB *pDati;
pDati = (LDB *)h_ogtNew->ogt_pDati;

/* alloca la memoria per la struttura di controllo dell'oggetto */
errore = NSC( h_ogtNew );
    if ( errore ) return errore;

h_ogtNew->ogt_pfDispatch = (FUNCTIONP)LISTA;

/* alloca la memoria per i dati dell'oggetto LISTA */

h_ogtNew->ogt_pDati = (LDB *)DosAllocMem( sizeof( LDB ) );

if ( !h_ogtNew->ogt_pDati ) {
    DSC( h_ogtNew );
    INFO_SET( METODO_CL , E_NOMEM_LD );
    return RETURN_FAIL;
} /* if */

NewList( (struct List *)&(pDati->ldbLista) );

return RETURN_OK;

} /* Fine di M_CREA_R */

/*------------------------------------------------------------
    M_DIST_O: De-alloca il buffer e distrugge l'oggetto.
              IMPORTANTE: il puntatore all'oggetto DEVE essere
              invalidato dal programma client. ( per ora! )
*/

static int M_DIST_O( h_ogtOld )
POGT h_ogtOld;

{
LTB *p_ltbItem;

/* Assegno un ptr temporaneo con un cast per evitare casini */
LDB *pDati;
pDati = (LDB *)h_ogtOld->ogt_pDati;

/* qui il codice svuotamento lista */
p_ltbItem = (LTB *)(pDati->ldbLista.lh_Head);

while( 1 ) {
    p_ltbItem = (LTB *)RemTail( &(pDati->ldbLista) );

    if ( p_ltbItem != NULL ) {
        DosFreeMem( p_ltbItem->ltbData );
        FreeMem( (LTB *)p_ltbItem , (long)sizeof( LTB ) );
    } /* if */
    else
        break;

} /* while */

DosFreeMem( h_ogtOld->ogt_pDati );
DSC( h_ogtOld );

return RETURN_OK;

} /* Fine di M_DIST_O */

/*-------------------------------------------------------------------
    F_CREA_ITEM: Funzione che alloca la memoria per un ITEM di LISTA.
*/

int F_CREA_ITEM (h_ogtAdd , pLap , pfAdd )
POGT  h_ogtAdd;
CADDR pLap;
void (*pfAdd)();

{
#define FUNZIONE_CI  "Metodo di aggiunta ITEM a LISTA."
#define E_NOMEM_ITEM "ERRORE: Fallita AllocMem per ITEM."

struct List *pL;
LTB *Litem;

/* Assegno un ptr temporaneo con un cast per evitare casini */
LDB *pDati;
pDati = (LDB *)h_ogtAdd->ogt_pDati;

pL = (struct List *)&(pDati->ldbLista);

Litem = (LTB *)AllocMem( sizeof( LTB ), MEMF_PUBLIC|MEMF_CLEAR );

    if ( !Litem ) {
        INFO_SET( FUNZIONE_CI , E_NOMEM_ITEM );
        return RETURN_FAIL;
    } /* if */

Litem->ltbData = pLap;
(*pfAdd)( pL , (struct Node *)Litem );

return RETURN_OK;

} /* Fine di F_CREA_ITEM */

/*-----------------------------------------------
    M_ADDH_OP: Aggiunge ITEM in testa alla LISTA.
*/

int M_ADDH_OP ( h_ogtAdd , pLap )
POGT  h_ogtAdd;
CADDR pLap;

{
return F_CREA_ITEM( h_ogtAdd , pLap , AddHead );
} /* Fine di M_ADDH_OP */

/*-----------------------------------------------
    M_ADDT_OP: Aggiunge ITEM in fondo alla LISTA.
*/

int M_ADDT_OP ( h_ogtAdd , pLap )
POGT  h_ogtAdd;
CADDR pLap;

{
return F_CREA_ITEM( h_ogtAdd , pLap , AddTail );
} /* Fine di M_ADDT_OP */

/*--------------------------------------------------------------------
    F_REM_ITEM: Funzione che rimuove un nodo dalla testa o dalla coda.
*/

int F_REM_ITEM ( h_ogtRem , pLrr , pfRem )
POGT  h_ogtRem;
CADDR pLrr;
struct Node *(*pfRem)();

{
#define FUNZIONE_RI "Metodo di rimozione ITEM da LISTA."
#define E_NOITEM    "ERRORE: L'ITEM puntato non esiste."

struct List *pL;

/* Assegno un ptr temporaneo con un cast per evitare casini */
LDB *pDati;
pDati = (LDB *)h_ogtRem->ogt_pDati;

pL = (struct List *)&(pDati->ldbLista);

pLrr = (CADDR)(*pfRem)( pL );

    if ( !pLrr ) {
        INFO_SET( FUNZIONE_RI , E_NOITEM );
        return RETURN_FAIL;
    } /* if */

return RETURN_OK;

} /* Fine di F_REM_ITEM */

/*--------------------------------------------------
    M_REMH_OR: Rimuove ITEM dalla testa della LISTA.
*/

int M_REMH_OR ( h_ogtRem , pLrr )
POGT  h_ogtRem;
CADDR pLrr;

{
return F_REM_ITEM( h_ogtRem , pLrr , RemHead );
} /* Fine di M_REMH_OR */

/*------------------------------------------------
    M_REMT_OR: Rimuove ITEM dal fondo della LISTA.
*/

int M_REMT_OR ( h_ogtRem , pLrr )
POGT  h_ogtRem;
CADDR pLrr;

{
return F_REM_ITEM( h_ogtRem , pLrr , RemTail );
} /* Fine di M_REMT_OR */

/*-------------------------------------
    M_REM_OP: Rimuove ITEM dalla LISTA.
*/

int M_REM_OP ( h_ogtRem , pLrp )
POGT  h_ogtRem;
CADDR pLrp;

{
return RETURN_OK;
} /* Fine di M_REM_OP */

/*-------------------------------------------------------------
    M_GIVE_OPR: Restituisce il ptr all'ITEM numerato in pParam.
*/

int M_GIVE_OPR ( h_ogtGive , pLgp , pLgr )
POGT  h_ogtGive;
long  pLgp;
CADDR pLgr;

{
return RETURN_OK;
} /* Fine di M_GIVE_OPR */

/*------------------------------------------------------------------
    M_FORALL_OP: Esegue per ogni ITEM la funzione puntata in pParam.
*/

int M_FORALL_OP ( h_ogtAll , pLfp )
POGT      h_ogtAll;
FUNCTIONP pLfp;

{
return RETURN_OK;
} /* Fine di M_FORALL_OP */

/* fine del file */
