/* **********************************************************************

Programma ...... Spudclock.c
Autori ......... Robert E. Beaty & Helmut Bret Young
Versione ....... 1.2I, Giugno 1989
Scopo .......... Implementa un orologio parlante
Hardware ....... Amiga 512K + Kickstart V1.2 o V1.3
Software ....... Lattice C Compiler (V5.02) o Aztec C V3.6a
Sintassi ....... RUN spudclock [opzioni]
Note ........... Traduzione ed adattamento x EAD di Luigi R. Callegari

********************************************************************** */

#include <exec/types.h>
#include <exec/exec.h>
#include <devices/narrator.h>
#include <devices/timer.h>
#include <libraries/translator.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>
#include <ctype.h>

#ifdef LATTICE
#include <string.h>
#include <proto/dos.h>
#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/translator.h>
#include <proto/timer.h>
#else
#include <functions.h>
#endif

/* Definiamo qualche costante di comodo */

#define REVISION	        1
#define TASK_PRIORITY	        0
#define NORMAL_EXIT		0
#define NORMAL_START		0
#define QUICK_EXIT		-10
#define QUICK_START		-20
#define CANT_OPEN_INTUITION	-100
#define CANT_OPEN_TRANSLATOR	-200
#define CANT_OPEN_NARRATOR	-300
#define CANT_OPEN_TIMER		-400
#define CREATE_PORT_PROBLEMS	-500
#define CREATE_IO_PROBLEMS	-600
#define TRANSLATOR_NOT_WORKING	-700
#define QUARTER_HOUR		1
#define HALF_HOUR		2
#define HOUR			4
#define LITTLE			1
#define BIG			2
#define	AM_BIT			(1<<0)
#define PS_BIT			(1<<1)
#define	SA_BIT			(1<<2)
#define	EA_BIT			(1<<3)
#define	AV_BIT			(1<<4)
#define	S_BIT			(1<<5)

/* Ed ora le strutture globali */

struct timerequest timeReq;	/* La nostra strada per il timer */
struct MsgPort *clockPort = NULL, *writePort = NULL, 
               *replyPort = NULL, *timerPort = NULL;
struct narrator_rb *writeNarrator = NULL;
struct IntuitionBase *IntuitionBase;
struct Library *TranslatorBase = NULL;
struct DateStamp now;
struct PacketMessage {
	struct Message packet_message; /* Per il DOS */
	int alarm_mode,      /* Quanto spesso dare l'allarme */
	    prestart,        /* Se prestart degli speakers */
	    start_alarm,     /* Tempo di partenza */
	    end_alarm,       /* Tempo di chiusura */
	    alarm_volume,    /* Volume di lettura */
	    quit_flag;       /* Quando terminare */
	char salutation[80]; /* Un poco prima della fine */
        int change_flags,
            changing,
            listing;
	};
	
/* Variabili globali */

UBYTE *sampleInput, outputString[500];	 /* Per il traduttore */
SHORT rtnCode, error;
BYTE audChanMasks[4] = { 3, 5, 10, 12 }; /* Quali canali usare */
int signal, timer_signal, port_signal;	 /* Provenienza messaggio */
int alarm_mode, quit_flag, prestart, alarm_volume;
int start_alarm, end_alarm, alarm_time;
int hours_24, hours_12, minutes;
char *cp, salutation[80], alarm[120];
struct PacketMessage *incoming, *outgoing;

/* La funzione cprintf() stampa semplicemente sulla consolle,
eliminando codice inutile dovuto alla inclusione della 
printf() standard. ******************************************/

LONG cprintf( arg )
char *arg;
{
    LONG length;

    length = Write( Output(), arg, strlen(arg) );
    return( length );
}

/* Questa funzione consente la conversione di un numero intero in
stringa ASCII. Il valore deve essere inferiore a 9999 **********/

void itoa( carg, varg )
char *carg;
int varg;
{
    register int place = 0;

    if ( varg > 999 )
    {
        carg[place++] = '0' + (varg/1000);
        varg = varg - (1000*(varg/1000));
    }
    if ( (varg > 99) || (place != 0) )
    {
        carg[place++] = '0' + (varg/100);
        varg = varg - (100*(varg/100));
    }
    if ( (varg > 9) || (place != 0) )
    {
        carg[place++] = '0' + (varg/10);
        varg = varg - (10*(varg/10));
    }
    carg[place++] = '0' + varg;
    carg[place] = '\0';
}

/* La funzione CloseNarrator() chiude educatamente il narrrator ed
il translator ***************************************************/

void CloseNarrator( why )
int why;
{
    /* Verifica se chiamata da OpenNarrator() */
    if ( why != CANT_OPEN_NARRATOR )
        if ( writeNarrator != NULL ) CloseDevice( writeNarrator );

/* Iniziamo la cancellazione, ma solo di ciò che esiste ! */

    if ( writeNarrator != NULL )
        DeleteExtIO( writeNarrator );
    if ( writePort != NULL )
        DeletePort( writePort );
    if ( TranslatorBase != NULL )
        CloseLibrary( TranslatorBase );
}

/* OpenNarrator() apre i devices translator e narrator. Ritorna un
valore in caso di errore *****************************************/

OpenNarrator()
{
    int error;

    /* Apre Translator innanzitutto */
    TranslatorBase = (struct Library *)\
                     OpenLibrary( "translator.library", REVISION );
    if ( TranslatorBase == NULL ) return( CANT_OPEN_TRANSLATOR );
        
    sampleInput = "This is a test.";
    rtnCode = Translate(sampleInput,strlen(sampleInput),outputString,500);
    if ( rtnCode != 0 )
    {
        CloseLibrary( TranslatorBase );
        return( TRANSLATOR_NOT_WORKING );
    }

    /* Creazione porta al narrator */
    writePort=(struct MsgPort *) \
               CreatePort("SPUDclock.narrator",TASK_PRIORITY);
    if ( writePort == NULL )
    {
        CloseLibrary( TranslatorBase );
        return( CREATE_PORT_PROBLEMS );
    }

    /* Creazione I/O al narrator */
    writeNarrator = (struct narrator_rb *) \
                     CreateExtIO( writePort, sizeof(struct narrator_rb) );
    if ( writeNarrator == NULL )
    {
        DeletePort( writePort );
        CloseLibrary( TranslatorBase );
        return( CREATE_IO_PROBLEMS );
    }

    /* Fissa i valori di default per la porta del narrator */
    writeNarrator->ch_masks = audChanMasks;	/* maschera canale */
    writeNarrator->nm_masks = sizeof(audChanMasks);	/* dimensione */
    writeNarrator->message.io_Data = (APTR)outputString;	/* dati */
    writeNarrator->mouths = 0;
    writeNarrator->message.io_Command = CMD_WRITE; /* invia comando */

    /* Apre il device di narrator */
    error = OpenDevice("narrator.device",0,writeNarrator,TASK_PRIORITY);
    if ( error != 0 )
    {
        CloseNarrator( CANT_OPEN_NARRATOR );
        return( CANT_OPEN_NARRATOR );
    }
    
    return( FALSE ); /* Nessun errore ! */
}

/* init() apre tutto e ritorna un valore non FALSE per errori *******/
init( how )
int how;
{
    register int error;

    if ( IntuitionBase == NULL )
    {
        IntuitionBase = (struct IntuitionBase *)\
	                 OpenLibrary( "intuition.library", REVISION );
        if ( IntuitionBase == NULL ) return( CANT_OPEN_INTUITION );
    }
    
    /* Se partenza veloce, apre solo Intuition */
    if ( how == QUICK_START ) return( FALSE );

/* Apre porta di comunicazione con altre copie di SPUDClock */
    clockPort = (struct MsgPort *)CreatePort( "SPUDclock", TASK_PRIORITY );
    if ( clockPort == NULL )
    {
        CloseLibrary( IntuitionBase );
        return( CREATE_PORT_PROBLEMS );
    }

    /* Ora apre il narrator */
    error = OpenNarrator();
    if ( error )
    {
        DeletePort( clockPort );
        CloseLibrary( IntuitionBase );
        return( error );
    }
    
    /* Ora crea il timer */
    timerPort = (struct MsgPort *)\
                 CreatePort( "SPUDclock.timer", TASK_PRIORITY );
    if ( timerPort == NULL )
    {
        CloseNarrator( CANT_OPEN_TIMER );
        DeletePort( clockPort );
        CloseLibrary( IntuitionBase );	
        return( CREATE_PORT_PROBLEMS );
    }

    error=OpenDevice(TIMERNAME,UNIT_VBLANK,(char *)&timeReq,TASK_PRIORITY);
    if ( error != 0 )
    {
        DeletePort( timerPort );
        CloseNarrator( CANT_OPEN_TIMER );
        DeletePort( clockPort );
        CloseLibrary( IntuitionBase );
        return( CANT_OPEN_TIMER );
    }

    /* Tutto OK!, leggiamo i bits di segnalazione */
    timer_signal = 1 << timerPort -> mp_SigBit;
    port_signal = 1 << clockPort -> mp_SigBit;
    
    /* e leggiamo la struttura di request del timer */
    timeReq.tr_node.io_Message.mn_ReplyPort = timerPort;
    timeReq.tr_node.io_Command = TR_ADDREQUEST;
    timeReq.tr_node.io_Flags = 0;
    timeReq.tr_node.io_Error = 0;

    return( FALSE ); /* Nessun errore */
}

/* clean() esegue pulizia di tutte le allocazioni *********************/

void clean( why )
int why;
{
    /* Annulla la richiesta del timer in sospeso */
    if ( timeReq.tr_node.io_Message.mn_ReplyPort != NULL )
        AbortIO( (char *) &timeReq.tr_node );

    /* Se vogliamo una uscita veloce, saltiamo via questa roba */
    if ( why == QUICK_EXIT ) goto quick;

    /* Chiamiamo tutte le routines di deallocazione */
    if ( timerPort != NULL ) DeletePort( timerPort );
    CloseNarrator( why );
    if ( clockPort != NULL ) DeletePort( clockPort );
    quick:
    if ( IntuitionBase != NULL ) CloseLibrary( IntuitionBase );
}

/* bed_bye() procura un evento del timer al task *******************/
void bed_bye( how_much )
int how_much;
{
    /* Vediamo quanto dobbiamo stare a riposo */
    if ( how_much == LITTLE )
    {
        timeReq.tr_time.tv_secs = 5;	/* LITTLE = 5 sec. */
        timeReq.tr_time.tv_micro = 0;
    }
    else
    {
        timeReq.tr_time.tv_secs = 885;	/* BIG è 14 min 45 sec. */
        timeReq.tr_time.tv_micro = 0;
    }
    /* ... ed eseguiamo */
    SendIO( (char *) &timeReq.tr_node ); 
}

/* Questa routine formatta e legge a voce l'ora ***********************/

void speak_time( hrs, mins )
int hrs, mins;
{
    if ( prestart ) /* Se necessario prestart degli altoparlanti */
        cp = stpcpy( alarm, "t,," );
    else
        cp = alarm;
	
    /* Costruisce stringa da leggere, iniziando dal saluto */
    cp = stpcpy( cp, salutation );
    cp = stpcpy( cp, ", It is now " );
    if ( (alarm_mode == QUARTER_HOUR) && (mins == 45) )
    {
        cp = stpcpy( cp, "quarter till " );
        if ( (++hrs) == 13 ) hrs = 1;
    }
    /* Aggiunge sempre l'ora */
    switch( hrs ) {
        case 1 : cp = stpcpy( cp, "1 " );  break;
        case 2 : cp = stpcpy( cp, "2 " );  break;
        case 3 : cp = stpcpy( cp, "3 " );  break;
        case 4 : cp = stpcpy( cp, "4 " );  break;
        case 5 : cp = stpcpy( cp, "5 " );  break;
        case 6 : cp = stpcpy( cp, "6 " );  break;
        case 7 : cp = stpcpy( cp, "7 " );  break;
        case 8 : cp = stpcpy( cp, "8 " );  break;
        case 9 : cp = stpcpy( cp, "9 " );  break;
        case 10 : cp = stpcpy( cp, "ten " );  break;
	/* Il numero 11 suona megli detto 'eelaven' */
        case 11 : cp = stpcpy( cp, "eelaven " );  break;
        case 12 : cp = stpcpy( cp, "twelve " );  break;
    }
    /* Decodifica i modi differenti */
    switch( alarm_mode )
    {
        case QUARTER_HOUR :
            switch( mins )
	    {
                case 0 : cp = stpcpy( cp, "o'clock." );  break;
                case 15 : cp = stpcpy( cp, "fifteen." );  break;
                case 30 : cp = stpcpy( cp, "thirty." );  break;
                case 45 : cp = stpcpy( cp, "." );  break;
                default : cp = NULL;  break;
            }
            break;
        case HALF_HOUR :
            switch( mins ) {
                case 0 : cp = stpcpy( cp, "o'clock." );  break;
                case 30 : cp = stpcpy( cp, "thirty." );  break;
                default : cp = NULL;  break;
            }
            break;
        case HOUR :
            if ( mins == 0 )
                cp = stpcpy( cp, "o'clock." );
            else
                cp = NULL;
            break;
    }
    if ( cp != NULL ) {
        /*
         * ... aggiunge "Good morning..." o "Good night..."
         */
        if ( start_alarm != end_alarm )
	{
            if ( alarm_time == start_alarm )
                cp = stpcpy( cp, ",, Good Morning!" );
            if ( alarm_time == end_alarm )
                cp = stpcpy( cp, ",, Good Night." );
        }
        /* Translazione e lettura */

        rtnCode = Translate( alarm, strlen(alarm), outputString, 500 );
        writeNarrator -> sex = MALE;
        writeNarrator -> pitch = DEFPITCH;
        writeNarrator -> mode = ROBOTICF0;
        writeNarrator -> volume = alarm_volume;
        writeNarrator -> message.io_Data = (APTR)outputString;
        writeNarrator -> message.io_Length = strlen( outputString );
        DoIO( writeNarrator );
    }
}

/* usage() - Scrive informazioni ******************************/

usage( how_much )
int how_much;
{
 cprintf( "Usage:\n" );
 cprintf( "  run SPUDclock [-m greeting message] [-f] [-t] [-h] [-q] [-p] [-s ####] [-e ####] [-v ##]\n" );
 if ( how_much == LITTLE ) return( FALSE );
 cprintf( "Where:\n" );
 cprintf( "  -m messaggio di saluto, detto prima dell'orario\n" );
 cprintf( "  -f  - messaggio ogni quarto d'ora\n" );
 cprintf( "  -t  - messaggio ogni mezza ora\n" );
 cprintf( "  -h  - messaggio ogni ora\n" );
 cprintf( "  -p  - messaggio con 't' iniziale per amplificatori\n" );
 cprintf( "  -s #### - fissa l'orario corrente\n" );
 cprintf( "  -e #### - fissa l'orario di termine\n" );
 cprintf( "  -v ## - fissa il  volume di lettura, (0...64)\n" );
 cprintf( "  -q  - elimina dalla memoria le copie di SPUDClock\n" );
 cprintf( "  -l  - elenca i correnti valori usati da SPUDClock\n");
 cprintf( "  -d  - riposiziona valori al default, tranne quelli specificati\n");
 return( FALSE );
}

/* print_settings() stampa i valori settati attualmente ***************/

void print_settings()
{
    char out[5];
    
    cprintf("SPUDclock settings \n\n");

    cprintf("  Messaggio ogni  ");
    switch (alarm_mode)
    {
        case QUARTER_HOUR :
            cprintf("quarto d'ora\n");
            break;
        case HALF_HOUR :
            cprintf("mezza ora\n");
            break;
        case HOUR :
            cprintf("ora\n");
            break;
    }

    if (prestart)
        cprintf("  Amplificatore inizializzato con t\n");
    else
        cprintf("  Amplificatore non inizializzato con t\n");

    cprintf("  Orologio da ");      
    itoa(out,start_alarm);
    cprintf(out); cprintf("\n");

    cprintf("  Si fermerà ");    
    itoa(out,end_alarm);
    cprintf(out); cprintf("\n");

    cprintf("  Volume d'allarme ");
    itoa(out,alarm_volume);
    cprintf(out); cprintf("\n");

    cprintf("  Messagio di saluto:\n");
    cprintf("   ");
    cprintf(salutation); cprintf("\n");
}

main( argc, argv )
int argc;
char *argv[];
{
    int i;
    int change_flags,
        changing,
        listing;
	
/* Si definiscono i valori assunti per default */

    alarm_mode = HALF_HOUR;     /* ogni 30 minuti */
    prestart = FALSE;           /* non inizializza amplificatore */
    start_alarm = 830;          /* inizia alle 8:30 am */
    end_alarm = 2300;           /* finisce alle 11:00 pm */
    alarm_volume = 50;          /* volume non fastidioso */
    stpcpy( salutation, " " );  /* nessun saluto */
    cp = salutation;            /* trattamento messaggio */
    quit_flag = FALSE;          /* non siamo stati fermati */
    change_flags = 0;
    changing = FALSE;
    listing = FALSE;

    for ( i=1; i < argc; i++ )
    {
        if ( argv[i][0] == '-' )
	{
            switch( argv[i][1] ) 
	    {
                case 'f' :
                    change_flags |= AM_BIT;
                    alarm_mode = QUARTER_HOUR;
                    break;
                case 't' :
                    change_flags |= AM_BIT;
                    alarm_mode = HALF_HOUR;
                    break;
                case 'h' :
                    change_flags |= AM_BIT;
                    alarm_mode = HOUR;
                    break;
                case 'q' :
                    quit_flag = TRUE;
                    break;
                case 'p' :
                    change_flags |= PS_BIT;
                    prestart = TRUE;
                    break;
                case 's' :
                    change_flags |= SA_BIT;
                    i++;	
                    start_alarm = 0;
                    while((*argv[i] >= '0') && (*argv[i] <= '9'))
                        start_alarm =(start_alarm * 10) + *argv[i]++ - '0';
                    break;
                case 'e' :
                    change_flags |= EA_BIT;
                    i++;
                    end_alarm = 0;
                    while((*argv[i] >= '0') && (*argv[i] <= '9'))
                        end_alarm = (end_alarm * 10) + *argv[i]++ - '0';
                    break;
                case 'v' :
                    change_flags |= AV_BIT;
                    i++;
                    alarm_volume = 0;
                    while((*argv[i] >= '0') && (*argv[i] <= '9'))
                        alarm_volume=(alarm_volume * 10)+*argv[i]++ - '0';
                    break;
                case 'm' :
                    change_flags |= S_BIT;
                    /* legge saluto una parola per volta */
                    for ( i=i; (argv[i+1][0] != '-') && (i < argc); i++ ) {
                        cp = stpcpy( cp, argv[i+1] );
                        cp = stpcpy( cp, " ");
                    }    
                    break;
                case 'l' :
                    listing = TRUE;
                    break;
                case 'd' :
                    changing = TRUE;
                    break;
                default :
                    usage( LITTLE );	/* mostra formato corto */
                    exit( TRUE );
                    break;
            }
        }
        else
	{
            usage( BIG );	/* mostra formato esteso*/
            exit( TRUE );
        }
    }

    /* Verifichiamo se esiste già copia di SPUDClock */
    /* Assumiamo di sì e facciamo copia veloce */
    if ( (error=init( QUICK_START )) != FALSE )
    {
        if ( error == CANT_OPEN_INTUITION )
	{
            cprintf( "Non si apre Intuition!\n" );
            cprintf( "Verifica directory DEVS: o riparti\n" );
        }
        exit( error );
    } 
    clockPort = (struct MsgPort *) FindPort( "SPUDclock" );
    if ( clockPort != NULL )
    {
    /* Alloca messaggio per altro SPUDClock */
    
        outgoing = (struct PacketMessage *) \
	         AllocMem( sizeof(struct PacketMessage), MEMF_PUBLIC );
        if ( outgoing == NULL )
	{
            cprintf( "Memoria insufficiente per inviare messaggio\n" );
            cprintf( "alla copia di SPUDClock. Dovrai ripartire\n" );
            cprintf( "per potere modificare la copia di SPUDClock\n" );
            clean( QUICK_EXIT );
            exit( TRUE );
        }

        /* Alloca porta di risposta per il messaggio */
        replyPort = (struct MsgPort *) \
	             CreatePort( "SPUDclock.reply.port", TASK_PRIORITY );
        if ( replyPort == NULL )
	{
            cprintf( "Risorse insufficienti per inviare un messaggio\n" );
            cprintf( "alla copia in memoria di SPUDClock. Dovrai ripartire\n" );
            cprintf( "con un reset completo per potere lavorare su\n" );
            cprintf( "SPUDclock.\n" );
            FreeMem( outgoing, sizeof(struct PacketMessage) );
            clean( QUICK_EXIT );
            exit( TRUE );
        } 

        outgoing -> packet_message.mn_Node.ln_Type = NT_MESSAGE;
        outgoing -> packet_message.mn_ReplyPort = replyPort;
        outgoing -> packet_message.mn_Length = sizeof(struct PacketMessage);
	
        /* Legge lo status dal pacchetto */
        outgoing -> alarm_mode = alarm_mode;
        outgoing -> prestart = prestart;
        outgoing -> start_alarm = start_alarm;
        outgoing -> end_alarm = end_alarm;
        outgoing -> alarm_volume = alarm_volume;
        stpcpy( outgoing -> salutation, salutation );
        outgoing -> quit_flag = quit_flag;
        outgoing -> change_flags = change_flags;
        outgoing -> changing = changing;
        outgoing -> listing = listing;
        
        /* Invio messaggio ed attesa della risposta */
        PutMsg( clockPort, outgoing );
        WaitPort( replyPort );
        DeletePort( replyPort );
        FreeMem( outgoing, sizeof(struct PacketMessage) );
        clean( QUICK_EXIT );
        exit( TRUE );
    }

    cprintf( "SPUDclock v1.2 - \n" );
    
    if (listing) print_settings();

    if ( quit_flag ) {
        clean( QUICK_EXIT );
        exit( FALSE );
    }   /* end of quick quit */

    /* Serve soltanto una partenza */
    if ( (error=init( NORMAL_START )) != FALSE )
    {
        /* decodifica dell'errore */
        switch ( error ) {
            case CANT_OPEN_INTUITION :
                cprintf( "Non si apre Intuition, verifica DEVS:!!\n" );
                break;
            case CANT_OPEN_TRANSLATOR :
                cprintf( "Non si apre il Translator.device!\n" );
                cprintf( "Forse manca in DEVS: il file narrator.device.\n");
                break;
            case CANT_OPEN_NARRATOR :
                cprintf( "Non si apre il Narrator.device!\n" );
                cprintf( "Forse manca il file narrator.device in DEVS:\n");
                break;
            case CANT_OPEN_TIMER :
                cprintf( "Non si apre il Timer.device!\n" );
                break;
            case CREATE_PORT_PROBLEMS :
                cprintf( "Manca RAM: non s'apre la porta per messaggi!\n");
                break;
            case CREATE_IO_PROBLEMS :
                cprintf( "Manca RAM: non s'apre la porta per messaggi!\n" );
                break;
            case TRANSLATOR_NOT_WORKING :
                cprintf( "Problemi con il Translator, verifica DEVS:\n" );
                break;
            default :
                cprintf( "Sorry, SPUDclock ha dato un errore!\n" );
                break;
        }
        exit( error );
    }   
    bed_bye( LITTLE );

    while( TRUE )
    {
        /* Attendiamo il risveglio ... */
        signal = Wait( timer_signal | port_signal );
	
        /* Verifichiamo il timer */
        if ( signal & timer_signal )
	{
            /* Eliminiamo il messaggio */
            (void) GetMsg( timerPort );
	    
            /* Legge l'orario ora */
            DateStamp( &now );
	    
            /* Converte in ore e minuti */
            hours_24 = now.ds_Minute / 60;
            hours_12 = ( now.ds_Minute / 60 ) % 12;
            if ( hours_12 == 0 ) hours_12 = 12;
            minutes = now.ds_Minute % 60;

            if ( (minutes == 0) || (minutes == 15) \
	                        || (minutes == 30) || (minutes == 45) )
	    {
                /* invia una lunga chiamata */
                bed_bye( BIG );

                /* Vediamo se inviarlo all'altoparlante */
                alarm_time = hours_24 * 100 + minutes;
                if ( (alarm_time >= start_alarm) \
		  && (alarm_time <= end_alarm) )
                    speak_time( hours_12, minutes );
            }
            else 
	    {
                /* invia in fretta un altro messaggio di risveglio */
                bed_bye( LITTLE );
            }
        }
 
        /* Verifica la porta dell'orologio */

        if ( signal & port_signal )
	{
            /* Legge il messaggio */
            incoming = (struct PacketMessage *) GetMsg( clockPort );
	    
            /* Legge status del pacchetto */
            changing = incoming -> changing;
            change_flags = incoming -> change_flags;
            listing = incoming -> listing;
            quit_flag = incoming -> quit_flag;

            switch (changing)
	    {
                case FALSE :
                    if (change_flags & AM_BIT)
	                alarm_mode = incoming -> alarm_mode;
                    if (change_flags & PS_BIT)
                        prestart = incoming -> prestart;
                    if (change_flags & SA_BIT)
	                start_alarm = incoming -> start_alarm;
                    if (change_flags & EA_BIT)
	                end_alarm = incoming -> end_alarm;
                    if (change_flags & AV_BIT)
                        alarm_volume = incoming -> alarm_volume;
                    if (change_flags & S_BIT)
	                stpcpy( salutation, incoming -> salutation );
	            break;
	        case TRUE :
	            alarm_mode = incoming -> alarm_mode;
                    prestart = incoming -> prestart;
	            start_alarm = incoming -> start_alarm;
	            end_alarm = incoming -> end_alarm;
                    alarm_volume = incoming -> alarm_volume;
	            stpcpy( salutation, incoming -> salutation );
	            break;
	    }

            if (listing) print_settings();
            /* Poichè non abbiamo allocato il messaggio, rispondiamo */
            ReplyMsg( incoming );
            
	    /* Se flag di quit attivo, terminiamo */
            if ( quit_flag )
	    {
                clean( NORMAL_EXIT );	/* ripulisce tutto */
                exit( FALSE );
            }

        }
    }    
    return( FALSE );
}

/* ************************** FINE DEL FILE ***************************/
